icoa-cli 2.19.2 → 2.19.4
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/dist/commands/ai4ctf.js
CHANGED
|
@@ -36,7 +36,7 @@ export async function handleChatMessage(input) {
|
|
|
36
36
|
chatActive = false;
|
|
37
37
|
chatSession = null;
|
|
38
38
|
// Anonymous stats
|
|
39
|
-
fetch('https://practice.icoa2026.au
|
|
39
|
+
fetch('https://practice.icoa2026.au/api/icoa/demo-stats', {
|
|
40
40
|
method: 'POST',
|
|
41
41
|
headers: { 'Content-Type': 'application/json' },
|
|
42
42
|
body: JSON.stringify({ type: 'ai4ctf', tokensUsed: chatTokensUsed, timestamp: new Date().toISOString() }),
|
package/dist/commands/ctf.js
CHANGED
|
@@ -121,8 +121,12 @@ export function registerCtfCommands(program) {
|
|
|
121
121
|
console.log(chalk.white(' status ') + chalk.gray('Check score & budget'));
|
|
122
122
|
}
|
|
123
123
|
catch (err) {
|
|
124
|
-
spinner2.fail('Connection failed');
|
|
124
|
+
spinner2.fail('Connection test failed');
|
|
125
125
|
printError(err.message);
|
|
126
|
+
// Still save URL so user can retry
|
|
127
|
+
saveConfig({ ctfdUrl: url, sessionCookie: sessionCookie });
|
|
128
|
+
console.log();
|
|
129
|
+
printInfo('Connection saved. Try: join ' + url);
|
|
126
130
|
}
|
|
127
131
|
});
|
|
128
132
|
// ─── icoa ctf logout ───
|
|
@@ -73,7 +73,7 @@ export async function handleCtf4aiMessage(input) {
|
|
|
73
73
|
if (input === 'exit' || input === 'back' || input === 'quit') {
|
|
74
74
|
ctf4aiActive = false;
|
|
75
75
|
ctf4aiSession = null;
|
|
76
|
-
fetch('https://practice.icoa2026.au
|
|
76
|
+
fetch('https://practice.icoa2026.au/api/icoa/demo-stats', {
|
|
77
77
|
method: 'POST',
|
|
78
78
|
headers: { 'Content-Type': 'application/json' },
|
|
79
79
|
body: JSON.stringify({ type: 'ctf4ai', solved: false, tokensUsed: ctf4aiTokens, timestamp: new Date().toISOString() }),
|
|
@@ -90,7 +90,7 @@ export async function handleCtf4aiMessage(input) {
|
|
|
90
90
|
console.log(chalk.white(' The AI held its ground this time. 💪'));
|
|
91
91
|
ctf4aiActive = false;
|
|
92
92
|
ctf4aiSession = null;
|
|
93
|
-
fetch('https://practice.icoa2026.au
|
|
93
|
+
fetch('https://practice.icoa2026.au/api/icoa/demo-stats', {
|
|
94
94
|
method: 'POST',
|
|
95
95
|
headers: { 'Content-Type': 'application/json' },
|
|
96
96
|
body: JSON.stringify({ type: 'ctf4ai', solved: false, tokensUsed: ctf4aiTokens, timestamp: new Date().toISOString() }),
|
|
@@ -121,7 +121,7 @@ export async function handleCtf4aiMessage(input) {
|
|
|
121
121
|
console.log(chalk.gray(' This is prompt injection — a real AI vulnerability.'));
|
|
122
122
|
ctf4aiActive = false;
|
|
123
123
|
ctf4aiSession = null;
|
|
124
|
-
fetch('https://practice.icoa2026.au
|
|
124
|
+
fetch('https://practice.icoa2026.au/api/icoa/demo-stats', {
|
|
125
125
|
method: 'POST',
|
|
126
126
|
headers: { 'Content-Type': 'application/json' },
|
|
127
127
|
body: JSON.stringify({ type: 'ctf4ai', solved: true, tokensUsed: ctf4aiTokens, timestamp: new Date().toISOString() }),
|
package/dist/commands/exam.js
CHANGED
|
@@ -811,7 +811,7 @@ export function registerExamCommand(program) {
|
|
|
811
811
|
console.log();
|
|
812
812
|
drawProgress(0, 'Validating token...');
|
|
813
813
|
try {
|
|
814
|
-
const res = await fetch(`${serverUrl}
|
|
814
|
+
const res = await fetch(`${serverUrl}/api/icoa/exam-token`, {
|
|
815
815
|
method: 'POST',
|
|
816
816
|
headers: { 'Content-Type': 'application/json' },
|
|
817
817
|
body: JSON.stringify({ token: code.trim() }),
|
package/dist/lib/ctfd-client.js
CHANGED
|
@@ -137,22 +137,34 @@ export class CTFdClient {
|
|
|
137
137
|
return destPath;
|
|
138
138
|
}
|
|
139
139
|
async getTokenViaIcoaApi(username, password) {
|
|
140
|
-
|
|
140
|
+
const body = JSON.stringify({ name: username, password });
|
|
141
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
142
|
+
// Try via nginx proxy first (same origin, no port)
|
|
143
|
+
try {
|
|
144
|
+
const res = await fetch(`${this.baseUrl}/api/icoa/token`, {
|
|
145
|
+
method: 'POST', headers, body,
|
|
146
|
+
signal: AbortSignal.timeout(5000),
|
|
147
|
+
});
|
|
148
|
+
if (res.ok) {
|
|
149
|
+
const json = await res.json();
|
|
150
|
+
if (json.success && json.data?.token)
|
|
151
|
+
return json.data.token;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch { /* proxy not available */ }
|
|
155
|
+
// Fallback: direct port 9090
|
|
141
156
|
try {
|
|
142
157
|
const res = await fetch(`${this.baseUrl}:9090/api/icoa/token`, {
|
|
143
|
-
method: 'POST',
|
|
144
|
-
headers: { 'Content-Type': 'application/json' },
|
|
145
|
-
body: JSON.stringify({ name: username, password }),
|
|
158
|
+
method: 'POST', headers, body,
|
|
146
159
|
signal: AbortSignal.timeout(5000),
|
|
147
160
|
});
|
|
148
161
|
if (res.ok) {
|
|
149
162
|
const json = await res.json();
|
|
150
|
-
if (json.success && json.data?.token)
|
|
163
|
+
if (json.success && json.data?.token)
|
|
151
164
|
return json.data.token;
|
|
152
|
-
}
|
|
153
165
|
}
|
|
154
166
|
}
|
|
155
|
-
catch { /* API not available
|
|
167
|
+
catch { /* API not available */ }
|
|
156
168
|
return null;
|
|
157
169
|
}
|
|
158
170
|
async loginWithCredentials(username, password) {
|
package/dist/lib/exam-client.js
CHANGED
|
@@ -6,7 +6,23 @@ export class ExamClient {
|
|
|
6
6
|
this.token = token;
|
|
7
7
|
}
|
|
8
8
|
async request(method, path, body) {
|
|
9
|
-
|
|
9
|
+
// Try nginx proxy first, fallback to direct port
|
|
10
|
+
const urls = [
|
|
11
|
+
`${this.baseUrl}/api/icoa/exams${path}`,
|
|
12
|
+
`${this.baseUrl}:9090/api/icoa/exams${path}`,
|
|
13
|
+
];
|
|
14
|
+
let lastError = null;
|
|
15
|
+
for (const url of urls) {
|
|
16
|
+
try {
|
|
17
|
+
return await this._fetch(method, url, body);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
lastError = e;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
throw lastError || new Error('Exam API unreachable');
|
|
24
|
+
}
|
|
25
|
+
async _fetch(method, url, body) {
|
|
10
26
|
const res = await fetch(url, {
|
|
11
27
|
method,
|
|
12
28
|
headers: {
|