mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 01:01:39 -05:00
Fix potential xss
This commit is contained in:
parent
4aa6edc3cc
commit
fa4e368003
3 changed files with 55 additions and 13 deletions
|
|
@ -177,8 +177,10 @@ export class PlacesManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
createPlaceIcon(place) {
|
createPlaceIcon(place) {
|
||||||
const emoji = place.icon || place.tags[0]?.icon || '📍';
|
const rawEmoji = place.icon || place.tags[0]?.icon || '📍';
|
||||||
const color = place.color || place.tags[0]?.color || '#4CAF50';
|
const emoji = this.escapeHtml(rawEmoji);
|
||||||
|
const rawColor = place.color || place.tags[0]?.color || '#4CAF50';
|
||||||
|
const color = this.sanitizeColor(rawColor);
|
||||||
|
|
||||||
const iconHtml = `
|
const iconHtml = `
|
||||||
<div class="place-marker" style="
|
<div class="place-marker" style="
|
||||||
|
|
@ -207,18 +209,24 @@ export class PlacesManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
createPopupContent(place) {
|
createPopupContent(place) {
|
||||||
const tags = place.tags.map(tag =>
|
const tags = place.tags.map(tag => {
|
||||||
`<span class="badge badge-sm" style="background-color: ${tag.color}">
|
const safeIcon = this.escapeHtml(tag.icon || '');
|
||||||
${tag.icon} #${tag.name}
|
const safeName = this.escapeHtml(tag.name || '');
|
||||||
</span>`
|
const safeColor = this.sanitizeColor(tag.color);
|
||||||
).join(' ');
|
return `<span class="badge badge-sm" style="background-color: ${safeColor}">
|
||||||
|
${safeIcon} #${safeName}
|
||||||
|
</span>`;
|
||||||
|
}).join(' ');
|
||||||
|
|
||||||
|
const safeName = this.escapeHtml(place.name || '');
|
||||||
|
const safeVisitsCount = place.visits_count ? parseInt(place.visits_count, 10) : 0;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="place-popup" style="min-width: 200px;">
|
<div class="place-popup" style="min-width: 200px;">
|
||||||
<h3 class="font-bold text-lg mb-2">${place.name}</h3>
|
<h3 class="font-bold text-lg mb-2">${safeName}</h3>
|
||||||
${tags ? `<div class="mb-2">${tags}</div>` : ''}
|
${tags ? `<div class="mb-2">${tags}</div>` : ''}
|
||||||
${place.note ? `<p class="text-sm text-gray-600 mb-2 italic">${this.escapeHtml(place.note)}</p>` : ''}
|
${place.note ? `<p class="text-sm text-gray-600 mb-2 italic">${this.escapeHtml(place.note)}</p>` : ''}
|
||||||
${place.visits_count ? `<p class="text-sm">Visits: ${place.visits_count}</p>` : ''}
|
${safeVisitsCount > 0 ? `<p class="text-sm">Visits: ${safeVisitsCount}</p>` : ''}
|
||||||
<div class="mt-2 flex gap-2">
|
<div class="mt-2 flex gap-2">
|
||||||
<button class="btn btn-xs btn-primary" data-place-id="${place.id}" data-action="edit-place">
|
<button class="btn btn-xs btn-primary" data-place-id="${place.id}" data-action="edit-place">
|
||||||
Edit
|
Edit
|
||||||
|
|
@ -237,6 +245,20 @@ export class PlacesManager {
|
||||||
return div.innerHTML;
|
return div.innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sanitizeColor(color) {
|
||||||
|
// Validate hex color format (#RGB or #RRGGBB)
|
||||||
|
if (!color || typeof color !== 'string') {
|
||||||
|
return '#4CAF50'; // Default green
|
||||||
|
}
|
||||||
|
|
||||||
|
const hexColorRegex = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
|
||||||
|
if (hexColorRegex.test(color)) {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '#4CAF50'; // Default green for invalid colors
|
||||||
|
}
|
||||||
|
|
||||||
setupMapClickHandler() {
|
setupMapClickHandler() {
|
||||||
this.map.on('click', (e) => {
|
this.map.on('click', (e) => {
|
||||||
if (this.creationMode) {
|
if (this.creationMode) {
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,10 @@ export function createPlacesControl(placesManager, tags, userTheme = 'dark') {
|
||||||
FILTER BY TAG
|
FILTER BY TAG
|
||||||
</div>
|
</div>
|
||||||
<div style="max-height: 250px; overflow-y: auto; margin-right: -5px; padding-right: 5px;">
|
<div style="max-height: 250px; overflow-y: auto; margin-right: -5px; padding-right: 5px;">
|
||||||
${this.tags.map(tag => `
|
${this.tags.map(tag => {
|
||||||
|
const safeIcon = tag.icon ? this.escapeHtml(tag.icon) : '📍';
|
||||||
|
const safeColor = this.sanitizeColor(tag.color);
|
||||||
|
return `
|
||||||
<label style="display: flex; align-items: center; padding: 6px; cursor: pointer; border-radius: 4px; margin-bottom: 2px;"
|
<label style="display: flex; align-items: center; padding: 6px; cursor: pointer; border-radius: 4px; margin-bottom: 2px;"
|
||||||
class="places-control-item"
|
class="places-control-item"
|
||||||
onmouseover="this.style.backgroundColor='rgba(128,128,128,0.2)'"
|
onmouseover="this.style.backgroundColor='rgba(128,128,128,0.2)'"
|
||||||
|
|
@ -110,11 +113,12 @@ export function createPlacesControl(placesManager, tags, userTheme = 'dark') {
|
||||||
data-tag-id="${tag.id}"
|
data-tag-id="${tag.id}"
|
||||||
style="margin-right: 8px; cursor: pointer;"
|
style="margin-right: 8px; cursor: pointer;"
|
||||||
${this.activeFilters.has(tag.id) ? 'checked' : ''}>
|
${this.activeFilters.has(tag.id) ? 'checked' : ''}>
|
||||||
<span style="font-size: 18px; margin-right: 6px;">${tag.icon || '📍'}</span>
|
<span style="font-size: 18px; margin-right: 6px;">${safeIcon}</span>
|
||||||
<span style="flex: 1;">#${this.escapeHtml(tag.name)}</span>
|
<span style="flex: 1;">#${this.escapeHtml(tag.name)}</span>
|
||||||
${tag.color ? `<span style="width: 12px; height: 12px; border-radius: 50%; background-color: ${tag.color}; margin-left: 4px;"></span>` : ''}
|
${tag.color ? `<span style="width: 12px; height: 12px; border-radius: 50%; background-color: ${safeColor}; margin-left: 4px;"></span>` : ''}
|
||||||
</label>
|
</label>
|
||||||
`).join('')}
|
`;
|
||||||
|
}).join('')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
` : '<div style="font-size: 12px; opacity: 0.6; padding: 8px; text-align: center;">No tags created yet</div>'}
|
` : '<div style="font-size: 12px; opacity: 0.6; padding: 8px; text-align: center;">No tags created yet</div>'}
|
||||||
|
|
@ -209,6 +213,20 @@ export function createPlacesControl(placesManager, tags, userTheme = 'dark') {
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.textContent = text;
|
div.textContent = text;
|
||||||
return div.innerHTML;
|
return div.innerHTML;
|
||||||
|
},
|
||||||
|
|
||||||
|
sanitizeColor: function(color) {
|
||||||
|
// Validate hex color format (#RGB or #RRGGBB)
|
||||||
|
if (!color || typeof color !== 'string') {
|
||||||
|
return '#4CAF50'; // Default green
|
||||||
|
}
|
||||||
|
|
||||||
|
const hexColorRegex = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
|
||||||
|
if (hexColorRegex.test(color)) {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '#4CAF50'; // Default green for invalid colors
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@ OMNIAUTH_PROVIDERS =
|
||||||
providers << :github if ENV['GITHUB_OAUTH_CLIENT_ID'].present? && ENV['GITHUB_OAUTH_CLIENT_SECRET'].present?
|
providers << :github if ENV['GITHUB_OAUTH_CLIENT_ID'].present? && ENV['GITHUB_OAUTH_CLIENT_SECRET'].present?
|
||||||
|
|
||||||
providers << :google_oauth2 if ENV['GOOGLE_OAUTH_CLIENT_ID'].present? && ENV['GOOGLE_OAUTH_CLIENT_SECRET'].present?
|
providers << :google_oauth2 if ENV['GOOGLE_OAUTH_CLIENT_ID'].present? && ENV['GOOGLE_OAUTH_CLIENT_SECRET'].present?
|
||||||
|
|
||||||
|
providers
|
||||||
end
|
end
|
||||||
|
|
||||||
# Custom OIDC provider display name
|
# Custom OIDC provider display name
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue