diff --git a/GrumpyCats/grumpycat.py b/GrumpyCats/grumpycat.py index 90e3274..500fb8f 100644 --- a/GrumpyCats/grumpycat.py +++ b/GrumpyCats/grumpycat.py @@ -316,32 +316,32 @@ class LitterBoxClient: def get_results(self, target: str, analysis_type: str) -> Dict: """Get results for a specific analysis type.""" self._validate_analysis_type(analysis_type, ['static', 'dynamic', 'info']) - response = self._make_request('GET', f'/results/{target}/{analysis_type}') + response = self._make_request('GET', f'/results/{analysis_type}/{target}') return response.json() def get_file_info(self, target: str) -> Dict: """Get file information via API endpoint.""" - response = self._make_request('GET', f'/api/results/{target}/info') + response = self._make_request('GET', f'/api/results/info/{target}') return response.json() def get_static_results(self, target: str) -> Dict: """Get static analysis results via API endpoint.""" - response = self._make_request('GET', f'/api/results/{target}/static') + response = self._make_request('GET', f'/api/results/static/{target}') return response.json() def get_dynamic_results(self, target: str) -> Dict: """Get dynamic analysis results via API endpoint.""" - response = self._make_request('GET', f'/api/results/{target}/dynamic') + response = self._make_request('GET', f'/api/results/dynamic/{target}') return response.json() def get_holygrail_results(self, target: str) -> Dict: """Get HolyGrail/BYOVD analysis results via API endpoint.""" - response = self._make_request('GET', f'/api/results/{target}/holygrail') + response = self._make_request('GET', f'/api/results/holygrail/{target}') return response.json() def get_risk_assessment(self, target: str) -> Dict: """Get the computed detection assessment (score, level, triggering indicators) for a target.""" - response = self._make_request('GET', f'/api/results/{target}/risk') + response = self._make_request('GET', f'/api/results/risk/{target}') return response.json() def get_files_summary(self) -> Dict: diff --git a/app/blueprints/api.py b/app/blueprints/api.py index 789fe4d..4c19a14 100644 --- a/app/blueprints/api.py +++ b/app/blueprints/api.py @@ -16,7 +16,7 @@ def _deps(): return current_app.extensions['litterbox'] -@api_bp.route('/api/results//static', methods=['GET']) +@api_bp.route('/api/results/static/', methods=['GET']) @error_handler def api_static_results(target): app = current_app @@ -36,7 +36,7 @@ def api_static_results(target): return jsonify(json.load(f)) -@api_bp.route('/api/results//dynamic', methods=['GET']) +@api_bp.route('/api/results/dynamic/', methods=['GET']) @error_handler def api_dynamic_results(target): app = current_app @@ -61,7 +61,7 @@ def api_dynamic_results(target): return jsonify(json.load(f)) -@api_bp.route('/api/results//info', methods=['GET']) +@api_bp.route('/api/results/info/', methods=['GET']) @error_handler def api_file_info(target): app = current_app @@ -81,7 +81,7 @@ def api_file_info(target): return jsonify(json.load(f)) -@api_bp.route('/api/results//holygrail', methods=['GET']) +@api_bp.route('/api/results/holygrail/', methods=['GET']) @error_handler def api_byovd_info(target): app = current_app @@ -185,7 +185,7 @@ def api_edr_agents_status(): return jsonify({"agents": results}) -@api_bp.route('/api/results//edr/', methods=['GET']) +@api_bp.route('/api/results/edr//', methods=['GET']) @error_handler def api_edr_results(target, profile): """Read the saved findings for a specific EDR profile run on `target`.""" @@ -203,7 +203,7 @@ def api_edr_results(target, profile): return jsonify(json.load(f)) -@api_bp.route('/api/results//edr', methods=['GET']) +@api_bp.route('/api/results/edr/', methods=['GET']) @error_handler def api_edr_index(target): """List which EDR profiles have saved results for `target`.""" @@ -220,7 +220,7 @@ def api_edr_index(target): return jsonify({'profiles': sorted(profiles)}) -@api_bp.route('/api/results//risk', methods=['GET']) +@api_bp.route('/api/results/risk/', methods=['GET']) @error_handler def api_risk_assessment(target): """Return the computed detection assessment (score, level, triggering indicators) for a target.""" diff --git a/app/blueprints/results.py b/app/blueprints/results.py index 9e60068..2185d36 100644 --- a/app/blueprints/results.py +++ b/app/blueprints/results.py @@ -15,7 +15,7 @@ def _deps(): return current_app.extensions['litterbox'] -@results_bp.route('/results//', methods=['GET']) +@results_bp.route('/results//', methods=['GET']) @error_handler def get_analysis_results(target, analysis_type): app = current_app diff --git a/app/services/rendering.py b/app/services/rendering.py index 02709aa..c1744ab 100644 --- a/app/services/rendering.py +++ b/app/services/rendering.py @@ -1,5 +1,5 @@ # app/services/rendering.py -"""Result-page render helpers for the /results// endpoint.""" +"""Result-page render helpers for the /results// endpoint.""" import os from flask import current_app, render_template diff --git a/app/static/js/byovd/core.js b/app/static/js/byovd/core.js index 59a0ebc..d7a8a67 100644 --- a/app/static/js/byovd/core.js +++ b/app/static/js/byovd/core.js @@ -1,5 +1,5 @@ // app/static/js/byovd/core.js -// /results//byovd page entry: fetches BYOVD analysis, renders verdict, +// /results/byovd/ page entry: fetches BYOVD analysis, renders verdict, // details, imports, YARA matches, and Win10/11 mitigation status. import { PERF_CONFIG, ElementCache, DOMUtils, AnimationSystem } from './utils.js'; @@ -60,7 +60,7 @@ class ByovdApp { // Parse path efficiently const pathSegments = window.location.pathname.split('/').filter(Boolean); - // Check for results pattern: /results/{hash}/byovd + // Check for results pattern: /results/byovd/{hash} const resultsIndex = pathSegments.indexOf('results'); if (resultsIndex !== -1 && pathSegments[resultsIndex + 1]) { return pathSegments[resultsIndex + 1]; @@ -167,7 +167,7 @@ class ByovdApp { console.log('[BYOVD] Fetching data from API...'); const data = await this.apiClient.fetch( - `/api/results/${encodeURIComponent(this.driverHash)}/holygrail`, + `/api/results/holygrail/${encodeURIComponent(this.driverHash)}`, { forceRefresh } ); diff --git a/app/static/js/results/core.js b/app/static/js/results/core.js index d3e93d1..f909b55 100644 --- a/app/static/js/results/core.js +++ b/app/static/js/results/core.js @@ -1,5 +1,5 @@ // app/static/js/results/core.js -// Entry point for the /results// page. +// Entry point for the /results// page. // Wires up TabManager, PayloadManager, AnalysisTypeHandler, ModalHandler // and the AnalysisCore poll loop. @@ -215,7 +215,7 @@ window.startHolyGrailScan = function() { .then(data => { if (data.status === 'success') { // Redirect to results page - window.location.href = `/results/${fileHash}/byovd`; + window.location.href = `/results/byovd/${fileHash}`; } else { // Handle error and restore button console.error('HolyGrail analysis failed:', data.error || data.message); diff --git a/app/static/js/results/tools/edr.js b/app/static/js/results/tools/edr.js index a7fc177..fe47ff3 100644 --- a/app/static/js/results/tools/edr.js +++ b/app/static/js/results/tools/edr.js @@ -11,7 +11,7 @@ // // On the initial POST response we render whatever Phase 1 produced. If // the status is `polling_alerts`, we kick off a foreground poll of GET -// /api/results//edr/ so the alerts pane and summary chip +// /api/results/edr// so the alerts pane and summary chip // reflect Phase 2 progress in real time. The block-vs-clean-exec // distinction is carried in `summary.blocked_by_av` — Phase 2 doesn't // fork its status on it because the polling itself is purely between @@ -595,7 +595,7 @@ function schedulePoll(profile) { if (!hash || !profile) return; _pollTimer = setTimeout(async () => { try { - const resp = await fetch(`/api/results/${encodeURIComponent(hash)}/edr/${encodeURIComponent(profile)}`, { + const resp = await fetch(`/api/results/edr/${encodeURIComponent(profile)}/${encodeURIComponent(hash)}`, { cache: 'no-store', }); if (!resp.ok) { diff --git a/app/static/js/summary.js b/app/static/js/summary.js index c8b2b9f..2d87207 100644 --- a/app/static/js/summary.js +++ b/app/static/js/summary.js @@ -443,15 +443,15 @@ function getDriverAnalysisStatus(driver) { // Action functions function viewFile(md5) { - window.location.href = `/results/${md5}/info`; + window.location.href = `/results/info/${md5}`; } function viewDriver(md5) { - window.location.href = `/results/${md5}/byovd`; + window.location.href = `/results/byovd/${md5}`; } function viewProcess(pid) { - window.location.href = `/results/${pid}/dynamic`; + window.location.href = `/results/dynamic/${pid}`; } function showFileDeleteWarning(md5) { diff --git a/app/static/js/upload/core.js b/app/static/js/upload/core.js index 2b4ec4b..a223958 100644 --- a/app/static/js/upload/core.js +++ b/app/static/js/upload/core.js @@ -641,7 +641,7 @@ document.addEventListener('DOMContentLoaded', function() { showToast('HolyGrail analysis completed successfully', 'success'); // Redirect to results page setTimeout(() => { - window.location.href = `/results/${currentFileHash}/byovd`; + window.location.href = `/results/byovd/${currentFileHash}`; }, 1000); } else { // Handle error diff --git a/app/static/js/utils/fetch.js b/app/static/js/utils/fetch.js index 69530a2..251bc97 100644 --- a/app/static/js/utils/fetch.js +++ b/app/static/js/utils/fetch.js @@ -50,7 +50,7 @@ export async function apiDelete(url, options = {}) { return response.json(); } -// Cached GET — useful for relatively-static endpoints (e.g. /api/results//info). +// Cached GET — useful for relatively-static endpoints (e.g. /api/results/info/). // Returns the cached promise on repeat calls; pass {forceRefresh:true} to bypass. const _cache = new Map(); export async function apiGetCached(url, { forceRefresh = false, ...options } = {}) { diff --git a/app/templates/byovd_info.html b/app/templates/byovd_info.html index a9b18fe..0d49cb0 100644 --- a/app/templates/byovd_info.html +++ b/app/templates/byovd_info.html @@ -33,7 +33,7 @@ Back to Summary {% if file_info %} - + Static Analysis diff --git a/app/templates/dynamic_info.html b/app/templates/dynamic_info.html index 81da31d..afe53eb 100644 --- a/app/templates/dynamic_info.html +++ b/app/templates/dynamic_info.html @@ -14,7 +14,7 @@
Dynamic Analysis Summary {% if file_info %} - diff --git a/app/templates/file_info.html b/app/templates/file_info.html index 5cd6a8c..3ee1eef 100644 --- a/app/templates/file_info.html +++ b/app/templates/file_info.html @@ -17,11 +17,11 @@ Back - - diff --git a/app/templates/static_info.html b/app/templates/static_info.html index e72fc17..4fd28f7 100644 --- a/app/templates/static_info.html +++ b/app/templates/static_info.html @@ -13,7 +13,7 @@
Static Analysis Summary -