Skip to content

Commit ff6bfda

Browse files
committed
Fixing synk vulnerability
1 parent 701584f commit ff6bfda

File tree

5 files changed

+189
-130
lines changed

5 files changed

+189
-130
lines changed

Diff for: app/auth/routes.py

+12-5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import asyncio
44
from functools import wraps
5+
import os
56
from urllib.parse import urljoin, urlparse
67

78
from bson import ObjectId
@@ -90,10 +91,17 @@ def on_blueprint_init(state):
9091

9192

9293
def is_safe_url(target):
94+
if not target:
95+
return False
96+
9397
ref_url = urlparse(request.host_url)
9498
test_url = urlparse(urljoin(request.host_url, target))
95-
return test_url.scheme in ('http', 'https') and \
96-
ref_url.netloc == test_url.netloc
99+
100+
return (
101+
test_url.scheme in ('http', 'https') and
102+
ref_url.netloc == test_url.netloc and
103+
not any(c in target for c in ['\\', '//', '..'])
104+
)
97105

98106

99107
@auth_bp.route("/login", methods=["GET", "POST"])
@@ -118,8 +126,7 @@ async def login():
118126
next_page = request.args.get('next')
119127
if not next_page or not is_safe_url(next_page):
120128
next_page = url_for('index')
121-
else:
122-
next_page = url_for(next_page)
129+
123130
flash("Successfully logged in", "success")
124131
return redirect(next_page)
125132

@@ -218,7 +225,7 @@ def profile_picture(user_id):
218225
"""Get user's profile picture"""
219226
user = user_manager.get_user_by_id(user_id)
220227
if not user or not user.profile_picture_id:
221-
return send_file("static/images/default_profile.png")
228+
return send_file(os.path.join(current_app.root_path, "static", "images", "default_profile.png"))
222229

223230
return send_gridfs_file(
224231
user.profile_picture_id,

Diff for: app/static/js/offline-storage.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,15 @@ async function syncPendingRequests() {
9595

9696
for (const request of pendingRequests) {
9797
try {
98-
const response = await fetch(request.url, {
98+
const url = new URL(request.url, window.location.origin);
99+
100+
if (url.origin !== window.location.origin) {
101+
console.error(`Invalid URL origin for request ${request.id}`);
102+
await offlineStorage.removePendingRequest(request.id);
103+
continue;
104+
}
105+
106+
const response = await fetch(url.toString(), {
99107
method: request.method,
100108
headers: new Headers(request.headers),
101109
body: request.body

Diff for: app/static/js/search.js

+56-33
Original file line numberDiff line numberDiff line change
@@ -91,47 +91,70 @@ document.addEventListener('DOMContentLoaded', function() {
9191
team.scouting_data.forEach(entry => {
9292
const row = document.createElement('tr');
9393

94-
// Format coral scores as L1/L2/L3/L4
94+
const createCell = (content) => {
95+
const td = document.createElement('td');
96+
td.className = 'px-6 py-4 whitespace-nowrap';
97+
if (typeof content === 'string' || typeof content === 'number') {
98+
td.textContent = content;
99+
} else {
100+
td.appendChild(content);
101+
}
102+
return td;
103+
};
104+
105+
// Format scores
95106
const autoCoral = `${entry.auto_coral_level1}/${entry.auto_coral_level2}/${entry.auto_coral_level3}/${entry.auto_coral_level4}`;
96107
const teleopCoral = `${entry.teleop_coral_level1}/${entry.teleop_coral_level2}/${entry.teleop_coral_level3}/${entry.teleop_coral_level4}`;
97-
98-
// Format algae scores as net/processor
99108
const autoAlgae = `${entry.auto_algae_net}/${entry.auto_algae_processor}`;
100109
const teleopAlgae = `${entry.teleop_algae_net}/${entry.teleop_algae_processor}/${entry.human_player || 0}`;
101-
102-
row.innerHTML = `
103-
<td class="px-6 py-4 whitespace-nowrap">${entry.event_code}</td>
104-
<td class="px-6 py-4 whitespace-nowrap">${entry.match_number}</td>
105-
<td class="px-6 py-4 whitespace-nowrap">${autoCoral}</td>
106-
<td class="px-6 py-4 whitespace-nowrap">${autoAlgae}</td>
107-
<td class="px-6 py-4 whitespace-nowrap">${teleopCoral}</td>
108-
<td class="px-6 py-4 whitespace-nowrap">${teleopAlgae}</td>
109-
<td class="px-6 py-4 whitespace-nowrap">
110-
${entry.climb_success ?
111-
`<span class="text-green-600">✓ ${entry.climb_type}</span>` :
112-
`<span class="text-red-600">✗ ${entry.climb_type || 'Failed'}</span>`}
113-
</td>
114-
<td class="px-6 py-4 whitespace-nowrap">
115-
${entry.auto_path ?
116-
`<button onclick="showAutoPath('${entry.auto_path}', '${entry.auto_notes}')"
117-
class="text-blue-600 hover:text-blue-900">
118-
View Path
119-
</button>` :
120-
`<span class="text-gray-400">No path</span>`}
121-
</td>
122-
<td class="px-6 py-4 whitespace-nowrap">${entry.defense_rating}/5</td>
123-
<td class="px-6 py-4 whitespace-nowrap">${entry.notes || ''}</td>
124-
<td class="px-6 py-4 whitespace-nowrap">${entry.scouter_name}</td>
125-
`;
110+
111+
// Create climb status cell
112+
const climbSpan = document.createElement('span');
113+
climbSpan.className = entry.climb_success ? 'text-green-600' : 'text-red-600';
114+
climbSpan.textContent = `${entry.climb_success ? '✓' : '✗'} ${entry.climb_type || 'Failed'}`;
115+
116+
// Create auto path cell
117+
const pathCell = document.createElement('td');
118+
pathCell.className = 'px-6 py-4 whitespace-nowrap';
119+
if (entry.auto_path) {
120+
const pathButton = document.createElement('button');
121+
pathButton.className = 'text-blue-600 hover:text-blue-900';
122+
pathButton.textContent = 'View Path';
123+
pathButton.addEventListener('click', () => {
124+
showAutoPath(entry.auto_path, entry.auto_notes);
125+
});
126+
pathCell.appendChild(pathButton);
127+
} else {
128+
const noPath = document.createElement('span');
129+
noPath.className = 'text-gray-400';
130+
noPath.textContent = 'No path';
131+
pathCell.appendChild(noPath);
132+
}
133+
134+
// Add all cells to the row
135+
row.append(
136+
createCell(entry.event_code),
137+
createCell(entry.match_number),
138+
createCell(autoCoral),
139+
createCell(autoAlgae),
140+
createCell(teleopCoral),
141+
createCell(teleopAlgae),
142+
createCell(climbSpan),
143+
pathCell,
144+
createCell(`${entry.defense_rating}/5`),
145+
createCell(entry.notes || ''),
146+
createCell(entry.scouter_name)
147+
);
148+
126149
scoutingTableBody.appendChild(row);
127150
});
128151
} else {
129152
const row = document.createElement('tr');
130-
row.innerHTML = `
131-
<td colspan="11" class="px-6 py-4 text-center text-gray-500">
132-
No scouting data available for this team
133-
</td>
134-
`;
153+
const cell = document.createElement('td');
154+
cell.colSpan = 11;
155+
cell.className = 'px-6 py-4 text-center text-gray-500';
156+
cell.textContent = 'No scouting data available for this team';
157+
row.appendChild(cell);
135158
scoutingTableBody.appendChild(row);
136159
}
137160

0 commit comments

Comments
 (0)