admin-lte 4.0.1 → 4.0.4

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.
Files changed (110) hide show
  1. package/ACCESSIBILITY-COMPLIANCE.md +60 -339
  2. package/CHANGELOG.md +53 -0
  3. package/README.md +15 -2
  4. package/dist/css/adminlte.css +24 -786
  5. package/dist/css/adminlte.css.map +1 -1
  6. package/dist/css/adminlte.min.css +2 -2
  7. package/dist/css/adminlte.min.css.map +1 -1
  8. package/dist/css/adminlte.rtl.css +24 -786
  9. package/dist/css/adminlte.rtl.css.map +1 -1
  10. package/dist/css/adminlte.rtl.min.css +2 -2
  11. package/dist/css/adminlte.rtl.min.css.map +1 -1
  12. package/dist/js/adminlte.js +233 -128
  13. package/dist/js/adminlte.js.map +1 -1
  14. package/dist/js/adminlte.min.js +2 -2
  15. package/dist/js/adminlte.min.js.map +1 -1
  16. package/package.json +30 -17
  17. package/src/scss/_callouts.scss +13 -3
  18. package/src/scss/_dropdown.scss +3 -1
  19. package/src/scss/adminlte.scss +1 -1
  20. package/src/scss/parts/_core.scss +0 -1
  21. package/src/ts/accessibility.ts +129 -69
  22. package/src/ts/adminlte.ts +1 -1
  23. package/src/ts/card-widget.ts +33 -8
  24. package/src/ts/fullscreen.ts +48 -42
  25. package/src/ts/layout.ts +2 -1
  26. package/src/ts/push-menu.ts +24 -8
  27. package/src/ts/treeview.ts +27 -1
  28. package/src/ts/util/index.ts +114 -29
  29. package/.browserslistrc +0 -17
  30. package/.prettierrc +0 -6
  31. package/CODE_OF_CONDUCT.md +0 -43
  32. package/SECURITY.md +0 -99
  33. package/dist/UI/general.html +0 -2317
  34. package/dist/UI/icons.html +0 -1126
  35. package/dist/UI/timeline.html +0 -1212
  36. package/dist/docs/browser-support.html +0 -826
  37. package/dist/docs/color-mode.html +0 -1142
  38. package/dist/docs/components/main-header.html +0 -1209
  39. package/dist/docs/components/main-sidebar.html +0 -924
  40. package/dist/docs/customization.html +0 -1080
  41. package/dist/docs/deployment.html +0 -1145
  42. package/dist/docs/faq.html +0 -1392
  43. package/dist/docs/getting-started.html +0 -991
  44. package/dist/docs/how-to-contribute.html +0 -890
  45. package/dist/docs/index.html +0 -16
  46. package/dist/docs/integrations.html +0 -1231
  47. package/dist/docs/introduction.html +0 -1008
  48. package/dist/docs/javascript/accessibility.html +0 -949
  49. package/dist/docs/javascript/card-widget.html +0 -1019
  50. package/dist/docs/javascript/direct-chat.html +0 -896
  51. package/dist/docs/javascript/fullscreen.html +0 -905
  52. package/dist/docs/javascript/layout.html +0 -908
  53. package/dist/docs/javascript/plugins-overview.html +0 -1144
  54. package/dist/docs/javascript/pushmenu.html +0 -1045
  55. package/dist/docs/javascript/treeview.html +0 -1024
  56. package/dist/docs/layout-blueprint.html +0 -1087
  57. package/dist/docs/layout.html +0 -842
  58. package/dist/docs/license.html +0 -807
  59. package/dist/docs/migration.html +0 -1149
  60. package/dist/docs/recipes.html +0 -1185
  61. package/dist/docs/rtl.html +0 -957
  62. package/dist/examples/lockscreen.html +0 -249
  63. package/dist/examples/login-v2.html +0 -282
  64. package/dist/examples/login.html +0 -272
  65. package/dist/examples/register-v2.html +0 -291
  66. package/dist/examples/register.html +0 -277
  67. package/dist/forms/elements.html +0 -1405
  68. package/dist/forms/layout.html +0 -1267
  69. package/dist/forms/validation.html +0 -1275
  70. package/dist/forms/wizard.html +0 -1410
  71. package/dist/generate/theme.html +0 -1082
  72. package/dist/index.html +0 -1745
  73. package/dist/index2.html +0 -2277
  74. package/dist/index3.html +0 -1532
  75. package/dist/layout/collapsed-sidebar-without-hover.html +0 -1144
  76. package/dist/layout/collapsed-sidebar.html +0 -1137
  77. package/dist/layout/fixed-complete.html +0 -1138
  78. package/dist/layout/fixed-footer.html +0 -1136
  79. package/dist/layout/fixed-header.html +0 -1136
  80. package/dist/layout/fixed-sidebar.html +0 -1138
  81. package/dist/layout/layout-custom-area.html +0 -1177
  82. package/dist/layout/layout-rtl.html +0 -1137
  83. package/dist/layout/logo-switch.html +0 -683
  84. package/dist/layout/sidebar-mini.html +0 -1137
  85. package/dist/layout/unfixed-sidebar.html +0 -1136
  86. package/dist/mailbox/compose.html +0 -1151
  87. package/dist/mailbox/inbox.html +0 -1509
  88. package/dist/mailbox/read.html +0 -1202
  89. package/dist/pages/404.html +0 -239
  90. package/dist/pages/500.html +0 -227
  91. package/dist/pages/calendar.html +0 -1266
  92. package/dist/pages/chat.html +0 -1427
  93. package/dist/pages/faq.html +0 -1383
  94. package/dist/pages/file-manager.html +0 -1835
  95. package/dist/pages/invoice.html +0 -1199
  96. package/dist/pages/kanban.html +0 -1439
  97. package/dist/pages/maintenance.html +0 -230
  98. package/dist/pages/pricing.html +0 -1279
  99. package/dist/pages/profile.html +0 -1382
  100. package/dist/pages/projects.html +0 -1644
  101. package/dist/pages/settings.html +0 -1387
  102. package/dist/tables/data.html +0 -1319
  103. package/dist/tables/simple.html +0 -1435
  104. package/dist/widgets/cards.html +0 -1356
  105. package/dist/widgets/info-box.html +0 -1429
  106. package/dist/widgets/small-box.html +0 -1225
  107. package/eslint.config.js +0 -82
  108. package/github-issue-response.md +0 -40
  109. package/index.html +0 -12
  110. package/netlify.toml +0 -16
@@ -42,6 +42,15 @@ type Config = {
42
42
  accordion: boolean;
43
43
  }
44
44
 
45
+ /**
46
+ * Reflect a submenu's open state on its toggle link so screen readers can
47
+ * announce the treeview as expandable/expanded (WCAG 4.1.2).
48
+ */
49
+ const setAriaExpanded = (navItem: Element, expanded: boolean): void => {
50
+ const link = navItem.querySelector(`:scope > ${SELECTOR_NAV_LINK}`)
51
+ link?.setAttribute('aria-expanded', String(expanded))
52
+ }
53
+
45
54
  /**
46
55
  * Class Definition
47
56
  * ====================================================
@@ -63,8 +72,13 @@ class Treeview {
63
72
  const openMenuList = this._element.parentElement?.querySelectorAll(`${SELECTOR_NAV_ITEM}.${CLASS_NAME_MENU_OPEN}`)
64
73
 
65
74
  openMenuList?.forEach(openMenu => {
66
- if (openMenu !== this._element.parentElement) {
75
+ // Skip the item being opened and anything nested inside it. The old
76
+ // guard compared against the parent <ul> — which never matches a
77
+ // nav-item — so calling open() on an already-open item slid its own
78
+ // menu shut.
79
+ if (!this._element.contains(openMenu)) {
67
80
  openMenu.classList.remove(CLASS_NAME_MENU_OPEN)
81
+ setAriaExpanded(openMenu, false)
68
82
  const childElement = openMenu?.querySelector(SELECTOR_TREEVIEW_MENU) as HTMLElement | undefined
69
83
  if (childElement) {
70
84
  slideUp(childElement, this._config.animationSpeed)
@@ -74,6 +88,7 @@ class Treeview {
74
88
  }
75
89
 
76
90
  this._element.classList.add(CLASS_NAME_MENU_OPEN)
91
+ setAriaExpanded(this._element, true)
77
92
 
78
93
  const childElement = this._element?.querySelector(SELECTOR_TREEVIEW_MENU) as HTMLElement | undefined
79
94
  if (childElement) {
@@ -87,6 +102,7 @@ class Treeview {
87
102
  const event = new Event(EVENT_COLLAPSED)
88
103
 
89
104
  this._element.classList.remove(CLASS_NAME_MENU_OPEN)
105
+ setAriaExpanded(this._element, false)
90
106
 
91
107
  const childElement = this._element?.querySelector(SELECTOR_TREEVIEW_MENU) as HTMLElement | undefined
92
108
  if (childElement) {
@@ -124,6 +140,16 @@ onDOMContentLoaded(() => {
124
140
  }
125
141
  })
126
142
 
143
+ // Stamp the initial ARIA state on every submenu toggle so assistive tech
144
+ // knows the items are expandable before any interaction.
145
+ document.querySelectorAll(SELECTOR_DATA_TOGGLE).forEach(root => {
146
+ root.querySelectorAll(SELECTOR_NAV_ITEM).forEach(item => {
147
+ if (item.querySelector(`:scope > ${SELECTOR_TREEVIEW_MENU}`)) {
148
+ setAriaExpanded(item, item.classList.contains(CLASS_NAME_MENU_OPEN))
149
+ }
150
+ })
151
+ })
152
+
127
153
  const button = document.querySelectorAll(SELECTOR_DATA_TOGGLE)
128
154
 
129
155
  button.forEach(btn => {
@@ -1,22 +1,80 @@
1
- const domContentLoadedCallbacks: Array<() => void> = []
1
+ /**
2
+ * Lifecycle management
3
+ * ============================================================================
4
+ *
5
+ * Plugins register their initialisation through `onDOMContentLoaded`. Besides
6
+ * the initial page load, every registered callback is re-run on Hotwired Turbo
7
+ * navigations (`turbo:load`): Turbo Drive swaps the <body> without a full page
8
+ * reload, so without re-initialisation plugins such as PushMenu and TreeView
9
+ * stop working after the first in-app link click (#563, #5890).
10
+ *
11
+ * Re-running init would normally leak listeners, because callbacks also bind to
12
+ * `window`/`document`, which survive Turbo's <body> swap. To prevent that, each
13
+ * cycle has its own `AbortController`: callbacks should attach their
14
+ * window/document-level listeners with the signal from `getLifecycleSignal()`.
15
+ * The signal is aborted on `turbo:before-render`, tearing down the previous
16
+ * cycle's listeners before the callbacks run again. Listeners bound to elements
17
+ * inside <body> don't need the signal — Turbo discards the old <body>, so they
18
+ * are cleaned up automatically.
19
+ */
20
+
21
+ const lifecycleCallbacks: Array<() => void> = []
22
+
23
+ // Mutable state is held on an object so the lifecycle hooks below can update it
24
+ // without reassigning top-level bindings.
25
+ const lifecycleState = {
26
+ controller: new AbortController(),
27
+ hasInitialized: false
28
+ }
29
+
30
+ /**
31
+ * The AbortSignal for the current lifecycle. Pass it as the
32
+ * `{ signal }` option to window/document `addEventListener` calls made during
33
+ * initialisation so they are removed automatically on the next Turbo render.
34
+ */
35
+ const getLifecycleSignal = (): AbortSignal => lifecycleState.controller.signal
36
+
37
+ const runLifecycleCallbacks = (): void => {
38
+ if (lifecycleState.hasInitialized) {
39
+ return
40
+ }
41
+
42
+ lifecycleState.hasInitialized = true
43
+
44
+ for (const callback of lifecycleCallbacks) {
45
+ callback()
46
+ }
47
+ }
2
48
 
3
49
  const onDOMContentLoaded = (callback: () => void): void => {
4
- if (document.readyState === 'loading') {
5
- // add listener on the first call when the document is in loading state
6
- if (!domContentLoadedCallbacks.length) {
7
- document.addEventListener('DOMContentLoaded', () => {
8
- for (const callback of domContentLoadedCallbacks) {
9
- callback()
10
- }
11
- })
12
- }
13
-
14
- domContentLoadedCallbacks.push(callback)
15
- } else {
50
+ lifecycleCallbacks.push(callback)
51
+
52
+ // Late registration: the batch for the current cycle has already run (the
53
+ // script loaded after DOMContentLoaded, or a callback was registered after a
54
+ // Turbo visit), so run the newcomer immediately rather than stranding it
55
+ // until the next navigation. Preserves the original non-loading behaviour.
56
+ if (lifecycleState.hasInitialized) {
16
57
  callback()
17
58
  }
18
59
  }
19
60
 
61
+ // Initial page load.
62
+ if (document.readyState === 'loading') {
63
+ document.addEventListener('DOMContentLoaded', runLifecycleCallbacks, { once: true })
64
+ } else {
65
+ runLifecycleCallbacks()
66
+ }
67
+
68
+ // Hotwired Turbo: drop the previous cycle's window/document listeners, then
69
+ // re-run initialisation against the freshly rendered <body>.
70
+ document.addEventListener('turbo:before-render', () => {
71
+ lifecycleState.controller.abort()
72
+ lifecycleState.controller = new AbortController()
73
+ lifecycleState.hasInitialized = false
74
+ })
75
+
76
+ document.addEventListener('turbo:load', runLifecycleCallbacks)
77
+
20
78
  /* ES2022 UTILITY FUNCTIONS */
21
79
 
22
80
  /**
@@ -46,10 +104,35 @@ const safePropertyAccess = (obj: Record<string, unknown>, property: string): unk
46
104
  }
47
105
  }
48
106
 
107
+ /* SLIDE ANIMATION BOOKKEEPING
108
+ * Pending timers are tracked per element so that starting a new slide cancels
109
+ * the previous animation's steps: without this, rapidly toggling a treeview or
110
+ * card leaves a stale cleanup timer that strips height/transition mid-animation
111
+ * and desyncs the element's display state from its component's classes. */
112
+ const slideTimers = new WeakMap<HTMLElement, number[]>()
113
+
114
+ const cancelSlide = (target: HTMLElement): void => {
115
+ const timers = slideTimers.get(target) ?? []
116
+ for (const timer of timers) {
117
+ globalThis.clearTimeout(timer)
118
+ }
119
+
120
+ slideTimers.delete(target)
121
+ }
122
+
123
+ const clearSlideStyles = (target: HTMLElement): void => {
124
+ for (const property of ['height', 'padding-top', 'padding-bottom', 'margin-top', 'margin-bottom', 'overflow', 'transition-duration', 'transition-property']) {
125
+ target.style.removeProperty(property)
126
+ }
127
+ }
128
+
49
129
  /* SLIDE UP */
50
130
  const slideUp = (target: HTMLElement, duration = 500) => {
131
+ cancelSlide(target)
132
+
51
133
  if (duration <= 1) {
52
134
  target.style.display = 'none'
135
+ clearSlideStyles(target)
53
136
  return
54
137
  }
55
138
 
@@ -59,7 +142,7 @@ const slideUp = (target: HTMLElement, duration = 500) => {
59
142
  target.style.height = `${target.offsetHeight}px`
60
143
  target.style.overflow = 'hidden'
61
144
 
62
- globalThis.setTimeout(() => {
145
+ const stepTimer = globalThis.setTimeout(() => {
63
146
  target.style.height = '0'
64
147
  target.style.paddingTop = '0'
65
148
  target.style.paddingBottom = '0'
@@ -67,21 +150,22 @@ const slideUp = (target: HTMLElement, duration = 500) => {
67
150
  target.style.marginBottom = '0'
68
151
  }, 1)
69
152
 
70
- globalThis.setTimeout(() => {
153
+ const cleanupTimer = globalThis.setTimeout(() => {
71
154
  target.style.display = 'none'
72
- target.style.removeProperty('height')
73
- target.style.removeProperty('padding-top')
74
- target.style.removeProperty('padding-bottom')
75
- target.style.removeProperty('margin-top')
76
- target.style.removeProperty('margin-bottom')
77
- target.style.removeProperty('overflow')
78
- target.style.removeProperty('transition-duration')
79
- target.style.removeProperty('transition-property')
155
+ clearSlideStyles(target)
156
+ slideTimers.delete(target)
80
157
  }, duration)
158
+
159
+ slideTimers.set(target, [stepTimer, cleanupTimer])
81
160
  }
82
161
 
83
162
  /* SLIDE DOWN */
84
163
  const slideDown = (target: HTMLElement, duration = 500) => {
164
+ cancelSlide(target)
165
+ // Drop inline styles a cancelled slideUp may have left behind (height: 0,
166
+ // overflow: hidden, …) before measuring, or the natural height reads as 0.
167
+ clearSlideStyles(target)
168
+
85
169
  target.style.removeProperty('display')
86
170
  let { display } = globalThis.getComputedStyle(target)
87
171
 
@@ -103,7 +187,7 @@ const slideDown = (target: HTMLElement, duration = 500) => {
103
187
  target.style.marginTop = '0'
104
188
  target.style.marginBottom = '0'
105
189
 
106
- globalThis.setTimeout(() => {
190
+ const stepTimer = globalThis.setTimeout(() => {
107
191
  target.style.boxSizing = 'border-box'
108
192
  target.style.transitionProperty = 'height, margin, padding'
109
193
  target.style.transitionDuration = `${duration}ms`
@@ -114,12 +198,12 @@ const slideDown = (target: HTMLElement, duration = 500) => {
114
198
  target.style.removeProperty('margin-bottom')
115
199
  }, 1)
116
200
 
117
- globalThis.setTimeout(() => {
118
- target.style.removeProperty('height')
119
- target.style.removeProperty('overflow')
120
- target.style.removeProperty('transition-duration')
121
- target.style.removeProperty('transition-property')
201
+ const cleanupTimer = globalThis.setTimeout(() => {
202
+ clearSlideStyles(target)
203
+ slideTimers.delete(target)
122
204
  }, duration)
205
+
206
+ slideTimers.set(target, [stepTimer, cleanupTimer])
123
207
  }
124
208
 
125
209
  /* TOGGLE */
@@ -134,6 +218,7 @@ const slideToggle = (target: HTMLElement, duration = 500) => {
134
218
 
135
219
  export {
136
220
  onDOMContentLoaded,
221
+ getLifecycleSignal,
137
222
  slideUp,
138
223
  slideDown,
139
224
  slideToggle,
package/.browserslistrc DELETED
@@ -1,17 +0,0 @@
1
- # https://github.com/browserslist/browserslist#readme
2
- # Updated for ES2022 compatibility
3
-
4
- >= 0.5%
5
- last 2 major versions
6
- not dead
7
- Chrome >= 97
8
- Firefox >= 104
9
- Firefox ESR
10
- iOS >= 15.4
11
- Safari >= 15.4
12
- Edge >= 97
13
- not Explorer <= 11
14
- not ie 11
15
- not android 4.4.3
16
- not ios_saf < 15.4
17
- not kaios <= 2.5 # fix floating label issues in Firefox (see https://github.com/postcss/autoprefixer/issues/1533)
package/.prettierrc DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "semi": true,
3
- "singleQuote": true,
4
- "printWidth": 100,
5
- "tabWidth": 2
6
- }
@@ -1,43 +0,0 @@
1
- # Contributor Covenant Code of Conduct
2
-
3
- ## Our Pledge
4
-
5
- In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
-
7
- ## Our Standards
8
-
9
- Examples of behavior that contributes to creating a positive environment include:
10
-
11
- - Using welcoming and inclusive language
12
- - Being respectful of differing viewpoints and experiences
13
- - Gracefully accepting constructive criticism
14
- - Focusing on what is best for the community
15
- - Showing empathy towards other community members
16
-
17
- Examples of unacceptable behavior by participants include:
18
-
19
- - The use of sexualized language or imagery and unwelcome sexual attention or advances
20
- - Trolling, insulting/derogatory comments, and personal or political attacks
21
- - Public or private harassment
22
- - Publishing others' private information, such as a physical or electronic address, without explicit permission
23
- - Other conduct which could reasonably be considered inappropriate in a professional setting
24
-
25
- ## Our Responsibilities
26
-
27
- Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28
-
29
- Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30
-
31
- ## Scope
32
-
33
- This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34
-
35
- ## Enforcement
36
-
37
- Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at https://colorlib.com/wp/contact-us/. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38
-
39
- Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40
-
41
- ## Attribution
42
-
43
- This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 1.4, available at <https://www.contributor-covenant.org/version/1/4/code-of-conduct/>
package/SECURITY.md DELETED
@@ -1,99 +0,0 @@
1
- # Security Policy
2
-
3
- ## Reporting Security Issues
4
-
5
- If you discover a security vulnerability in AdminLTE, please report it by emailing the maintainers or opening a private security advisory on GitHub. We take security seriously and will respond promptly.
6
-
7
- ## Supported Versions
8
-
9
- | Version | Supported |
10
- | ------- | ------------------ |
11
- | 4.x | :white_check_mark: |
12
- | 3.x | :x: |
13
- | < 3.0 | :x: |
14
-
15
- ## Security Best Practices
16
-
17
- AdminLTE is a frontend admin dashboard template. When deploying applications built with AdminLTE, follow these security best practices:
18
-
19
- ### 1. Production Deployment
20
-
21
- - **Never expose `node_modules` directory** in production environments
22
- - **Remove demo/example files** (like `index2.html`, `index3.html`) from production builds
23
- - **Use a proper build process** that only includes necessary production assets
24
- - **Configure web server properly** to prevent directory traversal attacks
25
-
26
- ### 2. Build Process
27
-
28
- When deploying to production:
29
-
30
- ```bash
31
- # Build only production assets
32
- npm run production
33
-
34
- # Deploy only the dist/ directory contents you need
35
- # Typically: dist/js/adminlte.min.js and dist/css/adminlte.min.css
36
- ```
37
-
38
- ### 3. What NOT to Deploy
39
-
40
- Do not deploy these to production:
41
- - `node_modules/` directory
42
- - Example/demo HTML files (`index.html`, `index2.html`, `index3.html`, etc.)
43
- - Source files (`src/` directory)
44
- - Development configuration files
45
- - Documentation files
46
-
47
- ## Known CVE Issues
48
-
49
- ### CVE-2021-36471 (Disputed)
50
-
51
- **Status**: This CVE is **disputed** and does not represent a vulnerability in AdminLTE itself.
52
-
53
- **Issue**: CVE-2021-36471 claims AdminLTE 3.1.0 has a "Directory Traversal vulnerability" that allows remote attackers to view demo pages via `/admin/index2.html` and `/admin/index3.html`.
54
-
55
- **Clarification**:
56
- - The `index2.html` and `index3.html` files are **example/demo pages** intended for developer reference during development
57
- - This is **not a vulnerability in AdminLTE** - it is a **deployment misconfiguration** by website developers
58
- - The issue occurs when developers incorrectly deploy:
59
- - Their entire `node_modules` folder publicly
60
- - Demo/example files in production environments
61
- - Without proper web server configuration
62
-
63
- **Resolution**:
64
- - AdminLTE 4.x has restructured the project architecture with clear separation between development demos and production assets
65
- - Follow the production deployment best practices above
66
- - Only deploy the compiled production assets from `dist/js/` and `dist/css/`
67
- - The original CVE researcher acknowledged this should be classified as low/info severity, not critical
68
-
69
- **For More Information**:
70
- - [GitHub Issue #4948](https://github.com/ColorlibHQ/AdminLTE/issues/4948)
71
- - [CVE Record](https://www.cve.org/CVERecord?id=CVE-2021-36471) (marked as disputed)
72
-
73
- ## Secure Development
74
-
75
- ### Content Security Policy (CSP)
76
-
77
- When implementing AdminLTE in your application, consider adding appropriate Content Security Policy headers to prevent XSS attacks.
78
-
79
- ### Authentication & Authorization
80
-
81
- AdminLTE is a **UI template only** and does not include authentication or authorization. You must:
82
- - Implement proper authentication in your backend
83
- - Secure all API endpoints
84
- - Use HTTPS in production
85
- - Implement proper session management
86
- - Follow OWASP security guidelines
87
-
88
- ### Dependencies
89
-
90
- - Keep AdminLTE and its dependencies up to date
91
- - Regularly run `npm audit` to check for vulnerabilities
92
- - Review security advisories for Bootstrap and other dependencies
93
-
94
- ## Contact
95
-
96
- For security concerns, please contact the maintainers through:
97
- - GitHub Issues (for general questions)
98
- - GitHub Security Advisories (for sensitive security issues)
99
- - Project maintainer email (check package.json)