@cyberstrike-io/cyberstrike 1.1.14 → 1.1.15-beta.1
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.
- package/hackbrowser-worker.js +340 -42
- package/package.json +12 -12
- package/skill/aws-postexploit/SKILL.md +120 -0
- package/skill/azure-postexploit/SKILL.md +86 -0
- package/skill/cicd-attacks/SKILL.md +81 -0
- package/skill/ebpf-attacks/SKILL.md +184 -0
- package/skill/k8s-postexploit/SKILL.md +85 -0
- package/skill/macos-postexploit/SKILL.md +125 -0
- package/skill/windows-postexploit/SKILL.md +113 -0
- package/web/assets/{ghostty-web-nFGAkzUN.js → ghostty-web-EyEK4Ew6.js} +1 -1
- package/web/assets/{home-C1IdTiFP.js → home-SafXwlHS.js} +1 -1
- package/web/assets/{index-D2hzTwHf.js → index-C0CQ2ZN1.js} +89 -89
- package/web/assets/{session-qd_85VE9.js → session-WtE9tIH4.js} +26 -26
- package/web/index.html +1 -1
package/hackbrowser-worker.js
CHANGED
|
@@ -30981,7 +30981,8 @@ async function handle2FA(page) {
|
|
|
30981
30981
|
}
|
|
30982
30982
|
return false;
|
|
30983
30983
|
}
|
|
30984
|
-
|
|
30984
|
+
var savedBtnPos = null;
|
|
30985
|
+
async function waitForManualLogin(page, label, progress) {
|
|
30985
30986
|
let resolveReady;
|
|
30986
30987
|
const readyPromise = new Promise((resolve3) => {
|
|
30987
30988
|
resolveReady = resolve3;
|
|
@@ -30990,12 +30991,19 @@ async function waitForManualLogin(page, label) {
|
|
|
30990
30991
|
await page.exposeFunction(callbackName, () => {
|
|
30991
30992
|
resolveReady();
|
|
30992
30993
|
});
|
|
30993
|
-
const
|
|
30994
|
-
|
|
30994
|
+
const posCallbackName = label ? `__cyberstrikePos_${label}` : "__cyberstrikePos";
|
|
30995
|
+
await page.exposeFunction(posCallbackName, (left, top) => {
|
|
30996
|
+
savedBtnPos = { left, top };
|
|
30997
|
+
});
|
|
30998
|
+
const isFinal = !progress || progress.index >= progress.total - 1;
|
|
30999
|
+
const step = progress ? ` (${progress.index + 1}/${progress.total})` : "";
|
|
31000
|
+
const who = label ? label.toUpperCase() : "LOGIN";
|
|
31001
|
+
const topLine = isFinal ? `// ${who}${step} · LOGIN MANUALLY ⟶ START SCAN` : `// ${who}${step} · LOGIN MANUALLY ⟶ CONFIRM & NEXT`;
|
|
31002
|
+
const buttonText = isFinal ? "START SCAN" : "CONFIRM & NEXT ⟶";
|
|
30995
31003
|
const buttonId = label ? `__cyberstrike-ready-btn-${label}` : "__cyberstrike-ready-btn";
|
|
30996
31004
|
const styleId = "__cyberstrike-ready-btn-style";
|
|
30997
31005
|
const injectButton = async () => {
|
|
30998
|
-
await page.evaluate(({ btnId, btnText, topText, cbName, styleElId }) => {
|
|
31006
|
+
await page.evaluate(({ btnId, btnText, topText, cbName, styleElId, posCb, savedPos, isFinal: isFinal2 }) => {
|
|
30999
31007
|
if (document.getElementById(btnId))
|
|
31000
31008
|
return;
|
|
31001
31009
|
if (!document.getElementById(styleElId)) {
|
|
@@ -31022,9 +31030,8 @@ async function waitForManualLogin(page, label) {
|
|
|
31022
31030
|
`;
|
|
31023
31031
|
document.head.appendChild(style);
|
|
31024
31032
|
}
|
|
31025
|
-
const btn = document.createElement("
|
|
31033
|
+
const btn = document.createElement("div");
|
|
31026
31034
|
btn.id = btnId;
|
|
31027
|
-
btn.type = "button";
|
|
31028
31035
|
btn.style.cssText = [
|
|
31029
31036
|
"all: initial",
|
|
31030
31037
|
"position: fixed",
|
|
@@ -31040,17 +31047,29 @@ async function waitForManualLogin(page, label) {
|
|
|
31040
31047
|
"border: 1px solid #1f2937",
|
|
31041
31048
|
"color: #e5e7eb",
|
|
31042
31049
|
"font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', Menlo, Consolas, ui-monospace, monospace",
|
|
31043
|
-
"cursor:
|
|
31050
|
+
"cursor: grab",
|
|
31044
31051
|
"user-select: none",
|
|
31052
|
+
"touch-action: none",
|
|
31045
31053
|
"box-shadow: 0 0 0 1px rgba(34,211,238,0.15), 0 0 20px rgba(34,211,238,0.25), 0 8px 24px rgba(0,0,0,0.5)",
|
|
31046
31054
|
"transition: box-shadow 180ms ease-out, background 180ms ease-out",
|
|
31047
31055
|
"-webkit-font-smoothing: antialiased"
|
|
31048
31056
|
].join(";");
|
|
31057
|
+
if (savedPos) {
|
|
31058
|
+
btn.style.left = savedPos.left + "px";
|
|
31059
|
+
btn.style.top = savedPos.top + "px";
|
|
31060
|
+
btn.style.right = "auto";
|
|
31061
|
+
}
|
|
31049
31062
|
for (const corner of ["tl", "tr", "bl", "br"]) {
|
|
31050
31063
|
const b = document.createElement("span");
|
|
31051
31064
|
b.className = `__cs-br ${corner}`;
|
|
31052
31065
|
btn.appendChild(b);
|
|
31053
31066
|
}
|
|
31067
|
+
const topRow = document.createElement("span");
|
|
31068
|
+
topRow.style.cssText = "display: flex; align-items: center; gap: 8px;";
|
|
31069
|
+
const grip = document.createElement("span");
|
|
31070
|
+
grip.textContent = "⠿";
|
|
31071
|
+
grip.setAttribute("aria-hidden", "true");
|
|
31072
|
+
grip.style.cssText = "font-size: 12px; color: #22d3ee; opacity: 0.55; cursor: grab;";
|
|
31054
31073
|
const meta = document.createElement("span");
|
|
31055
31074
|
meta.textContent = topText;
|
|
31056
31075
|
meta.style.cssText = [
|
|
@@ -31060,9 +31079,20 @@ async function waitForManualLogin(page, label) {
|
|
|
31060
31079
|
"opacity: 0.75",
|
|
31061
31080
|
"text-transform: uppercase"
|
|
31062
31081
|
].join(";");
|
|
31063
|
-
|
|
31064
|
-
|
|
31065
|
-
|
|
31082
|
+
topRow.appendChild(grip);
|
|
31083
|
+
topRow.appendChild(meta);
|
|
31084
|
+
btn.appendChild(topRow);
|
|
31085
|
+
const action = document.createElement("button");
|
|
31086
|
+
action.type = "button";
|
|
31087
|
+
action.setAttribute("aria-label", isFinal2 ? "Start scan" : "Confirm login and open next");
|
|
31088
|
+
action.style.cssText = [
|
|
31089
|
+
"all: unset",
|
|
31090
|
+
"display: flex",
|
|
31091
|
+
"align-items: center",
|
|
31092
|
+
"gap: 8px",
|
|
31093
|
+
"cursor: pointer",
|
|
31094
|
+
"padding: 2px 0"
|
|
31095
|
+
].join(";");
|
|
31066
31096
|
const dot = document.createElement("span");
|
|
31067
31097
|
dot.style.cssText = [
|
|
31068
31098
|
"display: inline-block",
|
|
@@ -31082,23 +31112,102 @@ async function waitForManualLogin(page, label) {
|
|
|
31082
31112
|
"color: #22d3ee",
|
|
31083
31113
|
"text-transform: uppercase"
|
|
31084
31114
|
].join(";");
|
|
31085
|
-
|
|
31086
|
-
|
|
31087
|
-
btn.appendChild(
|
|
31088
|
-
|
|
31115
|
+
action.appendChild(dot);
|
|
31116
|
+
action.appendChild(txt);
|
|
31117
|
+
btn.appendChild(action);
|
|
31118
|
+
const hint = document.createElement("span");
|
|
31119
|
+
hint.textContent = "drag ⠿ to move";
|
|
31120
|
+
hint.style.cssText = ["font-size: 8px", "letter-spacing: 0.1em", "color: #6b7280", "margin-top: 1px"].join(";");
|
|
31121
|
+
btn.appendChild(hint);
|
|
31122
|
+
let dragging = false;
|
|
31123
|
+
let moved = false;
|
|
31124
|
+
let sx = 0;
|
|
31125
|
+
let sy = 0;
|
|
31126
|
+
let ox = 0;
|
|
31127
|
+
let oy = 0;
|
|
31128
|
+
let dragEndedAt = 0;
|
|
31129
|
+
btn.addEventListener("pointerdown", (e) => {
|
|
31130
|
+
if (action.contains(e.target))
|
|
31131
|
+
return;
|
|
31132
|
+
dragging = true;
|
|
31133
|
+
moved = false;
|
|
31134
|
+
const r = btn.getBoundingClientRect();
|
|
31135
|
+
ox = r.left;
|
|
31136
|
+
oy = r.top;
|
|
31137
|
+
sx = e.clientX;
|
|
31138
|
+
sy = e.clientY;
|
|
31139
|
+
btn.style.left = ox + "px";
|
|
31140
|
+
btn.style.top = oy + "px";
|
|
31141
|
+
btn.style.right = "auto";
|
|
31142
|
+
btn.style.cursor = "grabbing";
|
|
31143
|
+
btn.setPointerCapture(e.pointerId);
|
|
31144
|
+
e.preventDefault();
|
|
31145
|
+
});
|
|
31146
|
+
btn.addEventListener("pointermove", (e) => {
|
|
31147
|
+
if (!dragging)
|
|
31148
|
+
return;
|
|
31149
|
+
const dx = e.clientX - sx;
|
|
31150
|
+
const dy = e.clientY - sy;
|
|
31151
|
+
if (Math.abs(dx) + Math.abs(dy) > 4)
|
|
31152
|
+
moved = true;
|
|
31153
|
+
const w = btn.offsetWidth;
|
|
31154
|
+
const h = btn.offsetHeight;
|
|
31155
|
+
btn.style.left = Math.max(0, Math.min(window.innerWidth - w, ox + dx)) + "px";
|
|
31156
|
+
btn.style.top = Math.max(0, Math.min(window.innerHeight - h, oy + dy)) + "px";
|
|
31157
|
+
});
|
|
31158
|
+
const endDrag = (e) => {
|
|
31159
|
+
if (!dragging)
|
|
31160
|
+
return;
|
|
31161
|
+
dragging = false;
|
|
31162
|
+
btn.style.cursor = "grab";
|
|
31163
|
+
try {
|
|
31164
|
+
btn.releasePointerCapture(e.pointerId);
|
|
31165
|
+
} catch {}
|
|
31166
|
+
if (moved) {
|
|
31167
|
+
dragEndedAt = Date.now();
|
|
31168
|
+
const r = btn.getBoundingClientRect();
|
|
31169
|
+
window[posCb](r.left, r.top);
|
|
31170
|
+
}
|
|
31171
|
+
};
|
|
31172
|
+
btn.addEventListener("pointerup", endDrag);
|
|
31173
|
+
btn.addEventListener("pointercancel", endDrag);
|
|
31174
|
+
action.addEventListener("click", () => {
|
|
31175
|
+
if (Date.now() - dragEndedAt < 350)
|
|
31176
|
+
return;
|
|
31089
31177
|
window[cbName]();
|
|
31090
|
-
meta.textContent = "// SCANNING…";
|
|
31091
|
-
txt.textContent = "INITIATED";
|
|
31178
|
+
meta.textContent = isFinal2 ? "// SCANNING…" : "// LOGIN CONFIRMED";
|
|
31179
|
+
txt.textContent = isFinal2 ? "INITIATED" : "NEXT LOGIN ⟶";
|
|
31092
31180
|
dot.style.animation = "none";
|
|
31093
31181
|
dot.style.background = "#6b7280";
|
|
31094
31182
|
dot.style.boxShadow = "none";
|
|
31095
31183
|
txt.style.color = "#9ca3af";
|
|
31096
31184
|
meta.style.color = "#6b7280";
|
|
31185
|
+
action.style.cursor = "default";
|
|
31097
31186
|
btn.style.cursor = "default";
|
|
31098
31187
|
btn.style.opacity = "0.7";
|
|
31188
|
+
hint.style.display = "none";
|
|
31099
31189
|
});
|
|
31100
31190
|
document.body.appendChild(btn);
|
|
31101
|
-
|
|
31191
|
+
{
|
|
31192
|
+
const w = btn.offsetWidth;
|
|
31193
|
+
const h = btn.offsetHeight;
|
|
31194
|
+
const curLeft = parseFloat(btn.style.left || "");
|
|
31195
|
+
const curTop = parseFloat(btn.style.top || "");
|
|
31196
|
+
if (!Number.isNaN(curLeft))
|
|
31197
|
+
btn.style.left = Math.max(0, Math.min(window.innerWidth - w, curLeft)) + "px";
|
|
31198
|
+
if (!Number.isNaN(curTop))
|
|
31199
|
+
btn.style.top = Math.max(0, Math.min(window.innerHeight - h, curTop)) + "px";
|
|
31200
|
+
}
|
|
31201
|
+
}, {
|
|
31202
|
+
btnId: buttonId,
|
|
31203
|
+
btnText: buttonText,
|
|
31204
|
+
topText: topLine,
|
|
31205
|
+
cbName: callbackName,
|
|
31206
|
+
styleElId: styleId,
|
|
31207
|
+
posCb: posCallbackName,
|
|
31208
|
+
savedPos: savedBtnPos,
|
|
31209
|
+
isFinal
|
|
31210
|
+
}).catch(() => {});
|
|
31102
31211
|
};
|
|
31103
31212
|
await injectButton();
|
|
31104
31213
|
page.on("load", injectButton);
|
|
@@ -40912,8 +41021,9 @@ function classifyAuthUrl(url2) {
|
|
|
40912
41021
|
return null;
|
|
40913
41022
|
}
|
|
40914
41023
|
var INPUT_ROLES = new Set(["textbox", "combobox", "checkbox", "radio", "slider"]);
|
|
41024
|
+
var ACTION_ROLES = new Set(["button", "menuitem", "tab"]);
|
|
40915
41025
|
function generateFingerprint(elements) {
|
|
40916
|
-
return elements.filter((e) => INPUT_ROLES.has(e.role)).map((e) => `${e.role}:${e.label}:${e.type}:${e.enabled}`).sort().join("|");
|
|
41026
|
+
return elements.filter((e) => INPUT_ROLES.has(e.role) || ACTION_ROLES.has(e.role) && !e.inChrome).map((e) => `${e.role}:${e.label}:${e.type}:${e.enabled}`).sort().join("|");
|
|
40917
41027
|
}
|
|
40918
41028
|
function generateFullFingerprint(elements) {
|
|
40919
41029
|
return elements.filter((e) => e.label && e.role !== "link" && e.role !== "info").map((e) => [e.role, e.label, e.type, e.enabled, e.options || "", e.placeholder || ""].join(":")).sort().join("|");
|
|
@@ -41000,8 +41110,31 @@ function buildPlannerSnapshot(url2, elements, globalState, credId, viewportCente
|
|
|
41000
41110
|
// ../hackbrowser/src/scanner.ts
|
|
41001
41111
|
var log4 = Log.create({ service: "hackbrowser:scanner" });
|
|
41002
41112
|
var MAX_ELEMENTS = 50;
|
|
41113
|
+
var MAX_PER_TEMPLATE = 5;
|
|
41114
|
+
var REVEAL_MAX_STEPS = 10;
|
|
41115
|
+
var REVEAL_STEP_WAIT = 250;
|
|
41116
|
+
var EXPAND_MAX = 20;
|
|
41003
41117
|
async function collectInteractiveElements(page) {
|
|
41004
41118
|
return page.evaluate(() => {
|
|
41119
|
+
const FRAMEWORK_CLICK_ATTRS = [
|
|
41120
|
+
"wire:click",
|
|
41121
|
+
"hx-get",
|
|
41122
|
+
"hx-post",
|
|
41123
|
+
"hx-put",
|
|
41124
|
+
"hx-patch",
|
|
41125
|
+
"hx-delete",
|
|
41126
|
+
"ng-click",
|
|
41127
|
+
"x-on:click",
|
|
41128
|
+
"@click",
|
|
41129
|
+
"data-toggle",
|
|
41130
|
+
"data-bs-toggle",
|
|
41131
|
+
"data-hx-get",
|
|
41132
|
+
"data-hx-post",
|
|
41133
|
+
"data-hx-put",
|
|
41134
|
+
"data-hx-patch",
|
|
41135
|
+
"data-hx-delete",
|
|
41136
|
+
"data-ng-click"
|
|
41137
|
+
];
|
|
41005
41138
|
function isStructurallyVisible(el) {
|
|
41006
41139
|
const rect = el.getBoundingClientRect();
|
|
41007
41140
|
if (rect.width === 0 && rect.height === 0)
|
|
@@ -41011,7 +41144,9 @@ async function collectInteractiveElements(page) {
|
|
|
41011
41144
|
return false;
|
|
41012
41145
|
if (style.visibility === "hidden")
|
|
41013
41146
|
return false;
|
|
41014
|
-
|
|
41147
|
+
const tag = el.tagName.toLowerCase();
|
|
41148
|
+
const isFormControl = tag === "input" || tag === "select" || tag === "textarea";
|
|
41149
|
+
if (parseFloat(style.opacity) === 0 && !isFormControl)
|
|
41015
41150
|
return false;
|
|
41016
41151
|
if (el.getAttribute("aria-hidden") === "true")
|
|
41017
41152
|
return false;
|
|
@@ -41052,6 +41187,32 @@ async function collectInteractiveElements(page) {
|
|
|
41052
41187
|
const placeholder = el.placeholder;
|
|
41053
41188
|
if (placeholder)
|
|
41054
41189
|
return placeholder;
|
|
41190
|
+
if (el.tagName.toLowerCase() === "input") {
|
|
41191
|
+
const itype = el.type?.toLowerCase();
|
|
41192
|
+
if (itype === "image") {
|
|
41193
|
+
const alt = el.getAttribute("alt")?.trim();
|
|
41194
|
+
if (alt)
|
|
41195
|
+
return alt;
|
|
41196
|
+
}
|
|
41197
|
+
if (itype === "submit" || itype === "button" || itype === "image") {
|
|
41198
|
+
const val = el.value?.trim();
|
|
41199
|
+
if (val)
|
|
41200
|
+
return val;
|
|
41201
|
+
}
|
|
41202
|
+
}
|
|
41203
|
+
const root = el.getRootNode();
|
|
41204
|
+
if (root instanceof ShadowRoot && root.host) {
|
|
41205
|
+
const host = root.host;
|
|
41206
|
+
const hostAria = host.getAttribute("aria-label")?.trim();
|
|
41207
|
+
if (hostAria)
|
|
41208
|
+
return hostAria;
|
|
41209
|
+
const hostLabelAttr = host.getAttribute("label")?.trim();
|
|
41210
|
+
if (hostLabelAttr)
|
|
41211
|
+
return hostLabelAttr;
|
|
41212
|
+
const hostText = host.innerText?.trim();
|
|
41213
|
+
if (hostText && hostText.length < 80)
|
|
41214
|
+
return hostText;
|
|
41215
|
+
}
|
|
41055
41216
|
const name19 = el.getAttribute("name") || el.getAttribute("data-testid");
|
|
41056
41217
|
if (name19)
|
|
41057
41218
|
return name19;
|
|
@@ -41065,10 +41226,12 @@ async function collectInteractiveElements(page) {
|
|
|
41065
41226
|
const type = el.type?.toLowerCase();
|
|
41066
41227
|
if (tag === "button")
|
|
41067
41228
|
return "button";
|
|
41229
|
+
if (tag === "summary")
|
|
41230
|
+
return "button";
|
|
41068
41231
|
if (tag === "a" && el.getAttribute("href"))
|
|
41069
41232
|
return "link";
|
|
41070
41233
|
if (tag === "input") {
|
|
41071
|
-
if (type === "submit" || type === "button")
|
|
41234
|
+
if (type === "submit" || type === "button" || type === "image")
|
|
41072
41235
|
return "button";
|
|
41073
41236
|
if (type === "checkbox")
|
|
41074
41237
|
return "checkbox";
|
|
@@ -41088,12 +41251,20 @@ async function collectInteractiveElements(page) {
|
|
|
41088
41251
|
return "menuitem";
|
|
41089
41252
|
if (el.hasAttribute("onclick"))
|
|
41090
41253
|
return "button";
|
|
41254
|
+
for (const a of FRAMEWORK_CLICK_ATTRS)
|
|
41255
|
+
if (el.hasAttribute(a))
|
|
41256
|
+
return "button";
|
|
41091
41257
|
return "";
|
|
41092
41258
|
}
|
|
41259
|
+
function isEphemeralId(id) {
|
|
41260
|
+
if (/^:/.test(id) || /:r[0-9a-z]+:/i.test(id))
|
|
41261
|
+
return true;
|
|
41262
|
+
return /^(mui-\d|radix-|headlessui-|react-aria-|rc-_?\d|ember\d)/i.test(id);
|
|
41263
|
+
}
|
|
41093
41264
|
function buildCSSSelector(el) {
|
|
41094
41265
|
const tag = el.tagName.toLowerCase();
|
|
41095
41266
|
const id = el.getAttribute("id");
|
|
41096
|
-
if (id)
|
|
41267
|
+
if (id && !isEphemeralId(id))
|
|
41097
41268
|
return `${tag}#${CSS.escape(id)}`;
|
|
41098
41269
|
const name19 = el.getAttribute("name");
|
|
41099
41270
|
if (name19)
|
|
@@ -41103,7 +41274,7 @@ async function collectInteractiveElements(page) {
|
|
|
41103
41274
|
while (current && current !== document.documentElement) {
|
|
41104
41275
|
const aTag = current.tagName.toLowerCase();
|
|
41105
41276
|
const aId = current.getAttribute("id");
|
|
41106
|
-
if (aId)
|
|
41277
|
+
if (aId && !isEphemeralId(aId))
|
|
41107
41278
|
return `${aTag}#${CSS.escape(aId)} `;
|
|
41108
41279
|
const aCls = typeof current.className === "string" ? current.className.trim().split(/\s+/).filter((c) => c.length > 2)[0] : undefined;
|
|
41109
41280
|
if (aCls)
|
|
@@ -41153,8 +41324,26 @@ async function collectInteractiveElements(page) {
|
|
|
41153
41324
|
"[role=combobox]",
|
|
41154
41325
|
"[role=option]",
|
|
41155
41326
|
"[role=slider]",
|
|
41156
|
-
"[onclick]"
|
|
41327
|
+
"[onclick]",
|
|
41328
|
+
"summary",
|
|
41329
|
+
...FRAMEWORK_CLICK_ATTRS.map((a) => `[${CSS.escape(a)}]`)
|
|
41157
41330
|
].join(", ");
|
|
41331
|
+
function queryAllDeep(selector) {
|
|
41332
|
+
const out = [];
|
|
41333
|
+
const walk = (root) => {
|
|
41334
|
+
for (const el of root.querySelectorAll(selector))
|
|
41335
|
+
out.push(el);
|
|
41336
|
+
for (const host of root.querySelectorAll("*")) {
|
|
41337
|
+
if (host.closest("[data-cyberstrike-ui]"))
|
|
41338
|
+
continue;
|
|
41339
|
+
const sr = host.shadowRoot;
|
|
41340
|
+
if (sr)
|
|
41341
|
+
walk(sr);
|
|
41342
|
+
}
|
|
41343
|
+
};
|
|
41344
|
+
walk(document);
|
|
41345
|
+
return out;
|
|
41346
|
+
}
|
|
41158
41347
|
function serializeConstraints(el, type) {
|
|
41159
41348
|
const tag = el.tagName.toLowerCase();
|
|
41160
41349
|
if (tag !== "input" && tag !== "textarea")
|
|
@@ -41191,19 +41380,12 @@ async function collectInteractiveElements(page) {
|
|
|
41191
41380
|
const elements = [];
|
|
41192
41381
|
const seenCount = new Map;
|
|
41193
41382
|
const seenRoleSelectors = new Map;
|
|
41194
|
-
|
|
41195
|
-
if (el.closest("[data-cyberstrike-ui]"))
|
|
41196
|
-
continue;
|
|
41197
|
-
const role = getRole(el);
|
|
41198
|
-
if (!role)
|
|
41199
|
-
continue;
|
|
41200
|
-
const isSlider = role === "slider";
|
|
41201
|
-
if (!isSlider && !isStructurallyVisible(el))
|
|
41202
|
-
continue;
|
|
41383
|
+
function addElement(el, role, syntheticRole = false) {
|
|
41203
41384
|
const label = getLabel(el);
|
|
41204
41385
|
const tag = el.tagName.toLowerCase();
|
|
41205
41386
|
const type = el.type?.toLowerCase() || "";
|
|
41206
41387
|
const href = el.href || "";
|
|
41388
|
+
const isSlider = role === "slider";
|
|
41207
41389
|
const value = isSlider ? el.getAttribute("aria-valuenow") ?? el.value ?? "" : el.value || "";
|
|
41208
41390
|
const placeholder = el.placeholder || "";
|
|
41209
41391
|
const enabled = !el.disabled;
|
|
@@ -41214,12 +41396,13 @@ async function collectInteractiveElements(page) {
|
|
|
41214
41396
|
const count = (seenCount.get(dedupKey) ?? 0) + 1;
|
|
41215
41397
|
seenCount.set(dedupKey, count);
|
|
41216
41398
|
if (count > 3)
|
|
41217
|
-
|
|
41399
|
+
return;
|
|
41218
41400
|
const disambiguatedLabel = count > 1 ? `${label} (${count})` : label;
|
|
41219
41401
|
const ariaLabelRaw = (el.getAttribute("aria-label") || "").trim();
|
|
41220
41402
|
const safeAriaLabel = ariaLabelRaw.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
41221
|
-
const selectorRole = count > 1 ? "" : safeAriaLabel ? `role=${role}[name="${safeAriaLabel}"]` : `role=${role}`;
|
|
41403
|
+
const selectorRole = syntheticRole || count > 1 ? "" : safeAriaLabel ? `role=${role}[name="${safeAriaLabel}"]` : `role=${role}`;
|
|
41222
41404
|
const selectorCSS = buildCSSSelector(el);
|
|
41405
|
+
const inChrome = !!el.closest("nav, header, footer, aside, [role=navigation], [role=banner], [role=contentinfo], [role=complementary]");
|
|
41223
41406
|
const roleCount = (seenRoleSelectors.get(selectorRole) ?? 0) + 1;
|
|
41224
41407
|
seenRoleSelectors.set(selectorRole, roleCount);
|
|
41225
41408
|
elements.push({
|
|
@@ -41234,9 +41417,45 @@ async function collectInteractiveElements(page) {
|
|
|
41234
41417
|
options,
|
|
41235
41418
|
constraints,
|
|
41236
41419
|
selectorRole,
|
|
41237
|
-
selectorCSS
|
|
41420
|
+
selectorCSS,
|
|
41421
|
+
inChrome
|
|
41238
41422
|
});
|
|
41239
41423
|
}
|
|
41424
|
+
for (const el of queryAllDeep(INTERACTIVE_SELECTORS)) {
|
|
41425
|
+
if (el.closest("[data-cyberstrike-ui]"))
|
|
41426
|
+
continue;
|
|
41427
|
+
const role = getRole(el);
|
|
41428
|
+
if (!role)
|
|
41429
|
+
continue;
|
|
41430
|
+
const isSlider = role === "slider";
|
|
41431
|
+
if (!isSlider && !isStructurallyVisible(el))
|
|
41432
|
+
continue;
|
|
41433
|
+
addElement(el, role);
|
|
41434
|
+
}
|
|
41435
|
+
for (const el of queryAllDeep("div, span, li")) {
|
|
41436
|
+
if (el.closest("[data-cyberstrike-ui]"))
|
|
41437
|
+
continue;
|
|
41438
|
+
if (el.getAttribute("role"))
|
|
41439
|
+
continue;
|
|
41440
|
+
if (el.hasAttribute("onclick"))
|
|
41441
|
+
continue;
|
|
41442
|
+
if (!isStructurallyVisible(el))
|
|
41443
|
+
continue;
|
|
41444
|
+
const text2 = el.innerText?.trim() || "";
|
|
41445
|
+
if (!text2 || text2.length > 80)
|
|
41446
|
+
continue;
|
|
41447
|
+
if (el.querySelector(INTERACTIVE_SELECTORS))
|
|
41448
|
+
continue;
|
|
41449
|
+
if (window.getComputedStyle(el).cursor !== "pointer")
|
|
41450
|
+
continue;
|
|
41451
|
+
const parent = el.parentElement;
|
|
41452
|
+
if (parent && window.getComputedStyle(parent).cursor === "pointer")
|
|
41453
|
+
continue;
|
|
41454
|
+
const rect = el.getBoundingClientRect();
|
|
41455
|
+
if (rect.width >= window.innerWidth * 0.9 && rect.height >= window.innerHeight * 0.5)
|
|
41456
|
+
continue;
|
|
41457
|
+
addElement(el, "button", true);
|
|
41458
|
+
}
|
|
41240
41459
|
const INTERACTIVE_TAGS = new Set(["input", "button", "a", "select", "textarea"]);
|
|
41241
41460
|
const INTERACTIVE_ROLES = new Set([
|
|
41242
41461
|
"button",
|
|
@@ -41285,7 +41504,8 @@ async function collectInteractiveElements(page) {
|
|
|
41285
41504
|
options: "",
|
|
41286
41505
|
constraints: "",
|
|
41287
41506
|
selectorRole: "",
|
|
41288
|
-
selectorCSS: ""
|
|
41507
|
+
selectorCSS: "",
|
|
41508
|
+
inChrome: false
|
|
41289
41509
|
});
|
|
41290
41510
|
}
|
|
41291
41511
|
for (const el of elements) {
|
|
@@ -41309,12 +41529,75 @@ function assignIds(browserElements, startId) {
|
|
|
41309
41529
|
placeholder: el.placeholder,
|
|
41310
41530
|
options: el.options,
|
|
41311
41531
|
constraints: el.constraints,
|
|
41312
|
-
selector: el.selectorRole.includes("[name=") ? el.selectorRole : el.selectorCSS || el.selectorRole
|
|
41532
|
+
selector: el.selectorRole.includes("[name=") ? el.selectorRole : el.selectorCSS || el.selectorRole,
|
|
41533
|
+
inChrome: el.inChrome
|
|
41313
41534
|
}));
|
|
41314
41535
|
}
|
|
41315
41536
|
async function collectElements(page) {
|
|
41316
41537
|
const browserElements = await collectInteractiveElements(page);
|
|
41317
|
-
|
|
41538
|
+
const sampled = sampleTemplates(browserElements);
|
|
41539
|
+
return assignIds(sampled, 1).slice(0, MAX_ELEMENTS);
|
|
41540
|
+
}
|
|
41541
|
+
function sampleTemplates(elements) {
|
|
41542
|
+
const clusterCount = new Map;
|
|
41543
|
+
const out = [];
|
|
41544
|
+
for (const el of elements) {
|
|
41545
|
+
const masked = el.label.replace(/\d+/g, "#");
|
|
41546
|
+
if (masked === el.label) {
|
|
41547
|
+
out.push(el);
|
|
41548
|
+
continue;
|
|
41549
|
+
}
|
|
41550
|
+
const key = `${el.role}::${masked}`;
|
|
41551
|
+
const n = (clusterCount.get(key) ?? 0) + 1;
|
|
41552
|
+
clusterCount.set(key, n);
|
|
41553
|
+
if (n <= MAX_PER_TEMPLATE)
|
|
41554
|
+
out.push(el);
|
|
41555
|
+
}
|
|
41556
|
+
return out;
|
|
41557
|
+
}
|
|
41558
|
+
async function revealLazyContent(page) {
|
|
41559
|
+
try {
|
|
41560
|
+
for (let i = 0;i < REVEAL_MAX_STEPS; i++) {
|
|
41561
|
+
const advanced = await page.evaluate(() => {
|
|
41562
|
+
const before = window.scrollY;
|
|
41563
|
+
window.scrollBy(0, Math.round(window.innerHeight * 0.9));
|
|
41564
|
+
return window.scrollY > before;
|
|
41565
|
+
});
|
|
41566
|
+
await page.waitForTimeout(REVEAL_STEP_WAIT);
|
|
41567
|
+
if (!advanced)
|
|
41568
|
+
break;
|
|
41569
|
+
}
|
|
41570
|
+
await page.evaluate(() => window.scrollTo(0, 0));
|
|
41571
|
+
await page.waitForTimeout(REVEAL_STEP_WAIT);
|
|
41572
|
+
} catch {}
|
|
41573
|
+
}
|
|
41574
|
+
async function expandDisclosures(page) {
|
|
41575
|
+
try {
|
|
41576
|
+
await page.evaluate((max) => {
|
|
41577
|
+
let budget = max;
|
|
41578
|
+
for (const d of Array.from(document.querySelectorAll("details:not([open])"))) {
|
|
41579
|
+
if (budget <= 0)
|
|
41580
|
+
break;
|
|
41581
|
+
if (d.closest("[data-cyberstrike-ui]"))
|
|
41582
|
+
continue;
|
|
41583
|
+
d.open = true;
|
|
41584
|
+
budget--;
|
|
41585
|
+
}
|
|
41586
|
+
for (const c of Array.from(document.querySelectorAll('[aria-expanded="false"]'))) {
|
|
41587
|
+
if (budget <= 0)
|
|
41588
|
+
break;
|
|
41589
|
+
if (c.closest("[data-cyberstrike-ui]"))
|
|
41590
|
+
continue;
|
|
41591
|
+
if (c.getAttribute("role") === "tab")
|
|
41592
|
+
continue;
|
|
41593
|
+
if (c.hasAttribute("aria-haspopup") && c.getAttribute("aria-haspopup") !== "false")
|
|
41594
|
+
continue;
|
|
41595
|
+
c.click();
|
|
41596
|
+
budget--;
|
|
41597
|
+
}
|
|
41598
|
+
}, EXPAND_MAX);
|
|
41599
|
+
await page.waitForTimeout(REVEAL_STEP_WAIT);
|
|
41600
|
+
} catch {}
|
|
41318
41601
|
}
|
|
41319
41602
|
async function isViewportCenterBlocked(page) {
|
|
41320
41603
|
try {
|
|
@@ -41588,7 +41871,13 @@ var PANEL_CSS = `
|
|
|
41588
41871
|
width: 360px;
|
|
41589
41872
|
background: #0b0f14;
|
|
41590
41873
|
border: 1px solid #1f2937;
|
|
41591
|
-
|
|
41874
|
+
/* Non-blocking HUD: the agent's own observability overlay must NEVER intercept
|
|
41875
|
+
clicks meant for the page. The card sits bottom-right where page chrome
|
|
41876
|
+
(cookie banners, chat widgets, FABs) commonly lives — pointer-events:auto here
|
|
41877
|
+
silently blocked those page elements (Playwright hit-test returns the panel →
|
|
41878
|
+
2s timeout per click). The panel is display-only; click-to-expand is sacrificed
|
|
41879
|
+
(re-add later via a keydown shortcut, which needs no pointer-events). */
|
|
41880
|
+
pointer-events: none;
|
|
41592
41881
|
transition: width 200ms ease-out, height 200ms ease-out;
|
|
41593
41882
|
box-shadow: 0 10px 40px -10px rgba(0,0,0,0.8);
|
|
41594
41883
|
overflow: hidden;
|
|
@@ -53190,7 +53479,12 @@ async function executeClickTask(task, page, elements, interceptor, semanticActio
|
|
|
53190
53479
|
targetSelector: el.selector,
|
|
53191
53480
|
credential: credentialId
|
|
53192
53481
|
});
|
|
53193
|
-
|
|
53482
|
+
let result = await execute(page, el, "click", undefined, interceptor.setPendingUI, elements.length);
|
|
53483
|
+
if (!result.success && await isViewportCenterBlocked(page)) {
|
|
53484
|
+
log6.debug("click blocked by a stray overlay — closing it and retrying once", { label: el.label });
|
|
53485
|
+
await closeOverlay(page);
|
|
53486
|
+
result = await execute(page, el, "click", undefined, interceptor.setPendingUI, elements.length);
|
|
53487
|
+
}
|
|
53194
53488
|
interceptor.clearPendingTrigger();
|
|
53195
53489
|
trackResult(result, interceptor, globalState, credentialId, task.triggersMutation, page);
|
|
53196
53490
|
csEmit(page, { type: "action-end", ok: result.success, credential: credentialId });
|
|
@@ -53530,7 +53824,7 @@ async function runMultiCredential(config2, credentials) {
|
|
|
53530
53824
|
const contexts = [];
|
|
53531
53825
|
const captureQueues = new Map;
|
|
53532
53826
|
const lastAuthHeaders = new Map;
|
|
53533
|
-
for (const cred of credentials) {
|
|
53827
|
+
for (const [credIndex, cred] of credentials.entries()) {
|
|
53534
53828
|
const browserContext = await browser.newContext({
|
|
53535
53829
|
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36"
|
|
53536
53830
|
});
|
|
@@ -53547,7 +53841,7 @@ async function runMultiCredential(config2, credentials) {
|
|
|
53547
53841
|
startedAt: Date.now()
|
|
53548
53842
|
});
|
|
53549
53843
|
csEmit(page, { type: "credential-switch", from: null, to: cred.id });
|
|
53550
|
-
await waitForManualLogin(page, cred.id);
|
|
53844
|
+
await waitForManualLogin(page, cred.id, { index: credIndex, total: credentials.length });
|
|
53551
53845
|
let credentialId = cred.id;
|
|
53552
53846
|
if (!dryRun) {
|
|
53553
53847
|
const registeredId = await registerCredential(serverUrl, sessionId, cred.id);
|
|
@@ -53662,6 +53956,8 @@ async function runMultiCredential(config2, credentials) {
|
|
|
53662
53956
|
await ctx.page.keyboard.press("Escape").catch(() => {});
|
|
53663
53957
|
await ctx.page.waitForTimeout(OVERLAY_ESCAPE_WAIT);
|
|
53664
53958
|
await dismissCookieBanner(ctx.page);
|
|
53959
|
+
await revealLazyContent(ctx.page);
|
|
53960
|
+
await expandDisclosures(ctx.page);
|
|
53665
53961
|
}
|
|
53666
53962
|
const elementsByContext = new Map;
|
|
53667
53963
|
const fingerprintsByContext = new Map;
|
|
@@ -53898,6 +54194,8 @@ async function run(config2) {
|
|
|
53898
54194
|
await page.waitForTimeout(OVERLAY_ESCAPE_WAIT);
|
|
53899
54195
|
}
|
|
53900
54196
|
await dismissCookieBanner(page);
|
|
54197
|
+
await revealLazyContent(page);
|
|
54198
|
+
await expandDisclosures(page);
|
|
53901
54199
|
const intel = getIntelligence(globalState, SINGLE_CRED);
|
|
53902
54200
|
const oldFingerprint = intel.pageFingerprints.get(currentUrl);
|
|
53903
54201
|
log6.debug("fingerprint check", { url: currentUrl, hasOld: !!oldFingerprint });
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"scripts": {
|
|
8
8
|
"postinstall": "bun ./postinstall.mjs || node ./postinstall.mjs"
|
|
9
9
|
},
|
|
10
|
-
"version": "1.1.
|
|
10
|
+
"version": "1.1.15-beta.1",
|
|
11
11
|
"license": "AGPL-3.0-only",
|
|
12
12
|
"keywords": [
|
|
13
13
|
"cyberstrike",
|
|
@@ -40,16 +40,16 @@
|
|
|
40
40
|
"playwright": "1.58.2"
|
|
41
41
|
},
|
|
42
42
|
"optionalDependencies": {
|
|
43
|
-
"@cyberstrike-io/cyberstrike-darwin-x64": "1.1.
|
|
44
|
-
"@cyberstrike-io/cyberstrike-windows-x64": "1.1.
|
|
45
|
-
"@cyberstrike-io/cyberstrike-darwin-x64-baseline": "1.1.
|
|
46
|
-
"@cyberstrike-io/cyberstrike-windows-x64-baseline": "1.1.
|
|
47
|
-
"@cyberstrike-io/cyberstrike-linux-x64-musl": "1.1.
|
|
48
|
-
"@cyberstrike-io/cyberstrike-linux-arm64-musl": "1.1.
|
|
49
|
-
"@cyberstrike-io/cyberstrike-linux-arm64": "1.1.
|
|
50
|
-
"@cyberstrike-io/cyberstrike-darwin-arm64": "1.1.
|
|
51
|
-
"@cyberstrike-io/cyberstrike-linux-x64-baseline-musl": "1.1.
|
|
52
|
-
"@cyberstrike-io/cyberstrike-linux-x64-baseline": "1.1.
|
|
53
|
-
"@cyberstrike-io/cyberstrike-linux-x64": "1.1.
|
|
43
|
+
"@cyberstrike-io/cyberstrike-darwin-x64": "1.1.15-beta.1",
|
|
44
|
+
"@cyberstrike-io/cyberstrike-windows-x64": "1.1.15-beta.1",
|
|
45
|
+
"@cyberstrike-io/cyberstrike-darwin-x64-baseline": "1.1.15-beta.1",
|
|
46
|
+
"@cyberstrike-io/cyberstrike-windows-x64-baseline": "1.1.15-beta.1",
|
|
47
|
+
"@cyberstrike-io/cyberstrike-linux-x64-musl": "1.1.15-beta.1",
|
|
48
|
+
"@cyberstrike-io/cyberstrike-linux-arm64-musl": "1.1.15-beta.1",
|
|
49
|
+
"@cyberstrike-io/cyberstrike-linux-arm64": "1.1.15-beta.1",
|
|
50
|
+
"@cyberstrike-io/cyberstrike-darwin-arm64": "1.1.15-beta.1",
|
|
51
|
+
"@cyberstrike-io/cyberstrike-linux-x64-baseline-musl": "1.1.15-beta.1",
|
|
52
|
+
"@cyberstrike-io/cyberstrike-linux-x64-baseline": "1.1.15-beta.1",
|
|
53
|
+
"@cyberstrike-io/cyberstrike-linux-x64": "1.1.15-beta.1"
|
|
54
54
|
}
|
|
55
55
|
}
|