Skip to content

Commit 1438dfa

Browse files
committed
Merge branch 'fix/s3-region-full-url'
2 parents 4b2ca6e + c513537 commit 1438dfa

5 files changed

Lines changed: 120 additions & 6 deletions

File tree

internal/api/ui/index.html

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,19 @@ <h1 class="auth-title">AutoAR</h1>
105105
<span class="nav-icon"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="13 17 18 12 13 7"/><polyline points="6 17 11 12 6 7"/></svg></span>
106106
<span>ADB Auditor</span>
107107
</div>
108-
<div class="nav-item" id="nav-securitylab" data-label="Security Lab">
108+
<div class="nav-item nav-group-head" id="nav-securitylab" data-label="Security Lab" aria-expanded="false">
109109
<span class="nav-icon"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2v17.5c0 1.4-1.1 2.5-2.5 2.5h0c-1.4 0-2.5-1.1-2.5-2.5V2"/><path d="M8.5 2h7"/><path d="M14.5 16h-5"/></svg></span>
110110
<span>Security Lab</span>
111+
<svg class="nav-caret" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
112+
</div>
113+
<div class="nav-subitems" id="securitylab-subnav" role="menu">
114+
<div class="nav-subitem" data-sltab="jwt" role="menuitem">JWT Analyzer</div>
115+
<div class="nav-subitem" data-sltab="regex" role="menuitem">Regex Workbench</div>
116+
<div class="nav-subitem" data-sltab="depconf" role="menuitem">Dependency Confusion</div>
117+
<div class="nav-subitem" data-sltab="ssrf" role="menuitem">SSRF Payloads</div>
118+
<div class="nav-subitem" data-sltab="xss" role="menuitem">XSS Cheat Sheet</div>
119+
<div class="nav-subitem" data-sltab="dorks" role="menuitem">Recon Dorks</div>
120+
<div class="nav-subitem" data-sltab="takeover" role="menuitem">Takeover Reference</div>
111121
</div>
112122

113123
<div class="nav-item" id="nav-r2" data-label="R2 Browser">

internal/api/ui/pages/router-navigation.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,26 @@
2626
adbauditor: '/ui/adbauditor/?mode=adb',
2727
};
2828
const frame = document.getElementById(`${view}-frame`);
29-
if (frame && !frame.getAttribute('data-loaded')) {
29+
if (view === 'securitylab') {
30+
// Deep-link a specific tool when chosen from the sidebar submenu.
31+
const slTab = state._securityLabTab;
32+
state._securityLabTab = null;
33+
if (frame && !frame.getAttribute('data-loaded')) {
34+
frame.setAttribute('data-loaded', '1');
35+
setTimeout(() => {
36+
try { frame.src = '/ui/securitylab/' + (slTab ? '#' + slTab : ''); }
37+
catch (e) { console.warn('[router] securitylab iframe init failed', e); }
38+
}, 30);
39+
} else if (frame && slTab) {
40+
// Already loaded — switch tab in place, no reload.
41+
try { frame.contentWindow.postMessage({ type: 'securitylab-tab', tab: slTab }, '*'); }
42+
catch (e) { /* ignore cross-frame edge cases */ }
43+
}
44+
} else if (frame && !frame.getAttribute('data-loaded')) {
3045
frame.setAttribute('data-loaded', '1');
3146
setTimeout(() => {
32-
try {
33-
if (view === 'securitylab') frame.src = '/ui/securitylab/';
34-
else frame.src = auditorPathMap[view] || `/ui/apkauditor/?mode=${modeMap[view]}`;
35-
} catch (e) {
47+
try { frame.src = auditorPathMap[view] || `/ui/apkauditor/?mode=${modeMap[view]}`; }
48+
catch (e) {
3649
// Keep SPA navigation alive even if iframe init fails in a browser/extension edge case.
3750
console.warn('[router] auditor iframe init failed', e);
3851
}

internal/api/ui/pages/shell-wiring.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,30 @@
1010
}
1111
});
1212

13+
// Security Lab is an expandable group: clicking the head toggles its tool list
14+
// (it still navigates via the handler above); each sub-item deep-links to one tool.
15+
const slHead = document.getElementById('nav-securitylab');
16+
if (slHead) {
17+
slHead.addEventListener('click', () => {
18+
const expanded = slHead.classList.toggle('expanded');
19+
slHead.setAttribute('aria-expanded', expanded ? 'true' : 'false');
20+
});
21+
}
22+
document.querySelectorAll('#securitylab-subnav .nav-subitem').forEach((el) => {
23+
el.addEventListener('click', (e) => {
24+
e.stopPropagation();
25+
const tab = el.dataset.sltab;
26+
document.querySelectorAll('#securitylab-subnav .nav-subitem').forEach((x) => x.classList.remove('active'));
27+
el.classList.add('active');
28+
if (slHead) {
29+
slHead.classList.add('expanded');
30+
slHead.setAttribute('aria-expanded', 'true');
31+
}
32+
window.state._securityLabTab = tab;
33+
window.navigateTo('securitylab');
34+
});
35+
});
36+
1337
const refreshBtn = document.getElementById('refresh-btn');
1438
if (refreshBtn) refreshBtn.addEventListener('click', window.manualRefresh);
1539

internal/api/ui/securitylab/index.html

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,23 @@ <h1 class="title">Security Lab</h1>
506506
});
507507
});
508508

509+
// Deep-linking: the parent dashboard can open a specific tool either via the URL
510+
// hash on first load (#ssrf) or via postMessage once the iframe is already loaded.
511+
// We click the tab button so any lazy initialization (e.g. XSS) also runs.
512+
(function () {
513+
function openTab(name) {
514+
if (!name) return;
515+
const btn = document.querySelector('.tab[data-tab="' + name + '"]');
516+
if (btn) btn.click();
517+
}
518+
openTab((location.hash || '').replace(/^#/, ''));
519+
window.addEventListener('hashchange', () => openTab((location.hash || '').replace(/^#/, '')));
520+
window.addEventListener('message', (e) => {
521+
const d = e.data;
522+
if (d && d.type === 'securitylab-tab' && typeof d.tab === 'string') openTab(d.tab);
523+
});
524+
})();
525+
509526
function pretty(v) { try { return JSON.stringify(v, null, 2); } catch { return String(v); } }
510527
function b64urlDecode(str) {
511528
const pad = '='.repeat((4 - (str.length % 4)) % 4);

internal/api/ui/styles.css

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,56 @@ input, select, textarea { font-family: inherit; }
275275
flex-shrink: 0;
276276
}
277277

278+
/* Expandable nav group (Security Lab) */
279+
.nav-caret {
280+
margin-left: auto;
281+
flex-shrink: 0;
282+
opacity: 0.55;
283+
transition: transform 0.18s ease, opacity var(--transition);
284+
}
285+
.nav-group-head:hover .nav-caret { opacity: 0.9; }
286+
.nav-group-head.expanded .nav-caret { transform: rotate(90deg); opacity: 0.9; }
287+
.nav-subitems {
288+
max-height: 0;
289+
overflow: hidden;
290+
transition: max-height 0.22s ease;
291+
display: flex;
292+
flex-direction: column;
293+
gap: 2px;
294+
}
295+
.nav-group-head.expanded + .nav-subitems { max-height: 340px; padding: 2px 0; }
296+
.nav-subitem {
297+
display: flex;
298+
align-items: center;
299+
padding: 7px 10px 7px 40px;
300+
border-radius: 8px;
301+
cursor: pointer;
302+
color: var(--text-secondary);
303+
font-size: 12.5px;
304+
font-weight: 500;
305+
white-space: nowrap;
306+
position: relative;
307+
transition: all var(--transition);
308+
}
309+
.nav-subitem::before {
310+
content: '';
311+
position: absolute;
312+
left: 26px;
313+
top: 50%;
314+
width: 5px;
315+
height: 5px;
316+
border-radius: 50%;
317+
background: currentColor;
318+
opacity: 0.35;
319+
transform: translateY(-50%);
320+
}
321+
.nav-subitem:hover { background: var(--bg-card); color: var(--text-primary); }
322+
.nav-subitem.active { color: var(--accent-cyan); background: var(--accent-cyan-dim); }
323+
.nav-subitem.active::before { opacity: 1; }
324+
/* Collapsed (icon-only) sidebar: hide the caret and the whole submenu. */
325+
.sidebar.collapsed .nav-caret,
326+
.sidebar.collapsed .nav-subitems { display: none; }
327+
278328
.nav-badge {
279329
margin-left: auto;
280330
background: var(--accent-cyan-dim);

0 commit comments

Comments
 (0)