icoa-cli 2.19.56 → 2.19.57
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/exam.js +73 -21
- package/package.json +1 -1
package/dist/commands/exam.js
CHANGED
|
@@ -335,8 +335,76 @@ function getHelpState(state) {
|
|
|
335
335
|
eliminated: state._eliminated || {},
|
|
336
336
|
};
|
|
337
337
|
}
|
|
338
|
-
//
|
|
339
|
-
|
|
338
|
+
// Section intros fire once per REPL session, first time the user enters
|
|
339
|
+
// that section. State-persisted via shownWarnings keys 's_ai4ctf' / 's_ctf4ai'
|
|
340
|
+
// so jumping back and forth doesn't re-fire them.
|
|
341
|
+
function printSectionIntro(state, currentQ) {
|
|
342
|
+
if (state.session.examId === 'demo-free')
|
|
343
|
+
return;
|
|
344
|
+
const total = Number(state.session.questionCount || 40);
|
|
345
|
+
// Only 40-question exams have the three-section structure
|
|
346
|
+
if (total < 40)
|
|
347
|
+
return;
|
|
348
|
+
const shown = new Set(state.shownWarnings || []);
|
|
349
|
+
// ─── AI4CTF section intro (Q31 = first practical, AI-as-teammate) ───
|
|
350
|
+
if (currentQ >= 31 && currentQ <= 38 && !shown.has('s_ai4ctf')) {
|
|
351
|
+
console.log();
|
|
352
|
+
console.log(chalk.green(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
353
|
+
console.log(chalk.bold.green(' 🚀 Section 2: AI4CTF — AI is your teammate'));
|
|
354
|
+
console.log(chalk.green(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
355
|
+
console.log();
|
|
356
|
+
console.log(chalk.white(' Welcome to the practical CTF section. Real'));
|
|
357
|
+
console.log(chalk.white(' security tasks — crypto, web, forensics, pwn.'));
|
|
358
|
+
console.log();
|
|
359
|
+
console.log(chalk.bold.white(' Q31–38 (8 questions · 6 pts each)'));
|
|
360
|
+
console.log(chalk.gray(' Solve ') + chalk.bold('with') + chalk.gray(' AI by your side. AI is your teammate.'));
|
|
361
|
+
console.log();
|
|
362
|
+
console.log(chalk.bold.white(' How to work'));
|
|
363
|
+
console.log(chalk.gray(' Run Python: ') + chalk.green('!python3 -c "print(1+1)"'));
|
|
364
|
+
console.log(chalk.gray(' ') + chalk.green('!python3') + chalk.gray(' for REPL'));
|
|
365
|
+
console.log(chalk.gray(' Ask AI: ') + chalk.bold.cyan('hint') + chalk.gray(' — free-form question'));
|
|
366
|
+
console.log(chalk.gray(' Submit flag: ') + chalk.green('exam answer <n> ICOA{...}'));
|
|
367
|
+
console.log();
|
|
368
|
+
console.log(chalk.bold.white(' Budget'));
|
|
369
|
+
console.log(chalk.gray(' AI tokens: ') + chalk.white('25,000') + chalk.gray(' for this section'));
|
|
370
|
+
console.log(chalk.gray(' Hints A/B/C: ') + chalk.white('5 / 3 / 1') + chalk.gray(' structured hints per question'));
|
|
371
|
+
console.log();
|
|
372
|
+
console.log(chalk.yellow(' Time still counting down. Budget ~2 min per question.'));
|
|
373
|
+
console.log(chalk.green(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
374
|
+
console.log();
|
|
375
|
+
shown.add('s_ai4ctf');
|
|
376
|
+
state.shownWarnings = Array.from(shown);
|
|
377
|
+
saveExamState(state);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
// ─── CTF4AI section intro (Q39 = adversarial AI, highest-value questions) ───
|
|
381
|
+
if (currentQ >= 39 && !shown.has('s_ctf4ai')) {
|
|
382
|
+
console.log();
|
|
383
|
+
console.log(chalk.red(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
384
|
+
console.log(chalk.bold.red(' 🎯 Section 3: CTF4AI — Challenge the AI'));
|
|
385
|
+
console.log(chalk.red(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
386
|
+
console.log();
|
|
387
|
+
console.log(chalk.white(' The final section flips the script: instead of'));
|
|
388
|
+
console.log(chalk.white(' using AI, you\'re ') + chalk.bold('attacking') + chalk.white(' AI systems.'));
|
|
389
|
+
console.log();
|
|
390
|
+
console.log(chalk.bold.white(' Q39–40 (2 questions · 16 pts each — highest value!)'));
|
|
391
|
+
console.log(chalk.gray(' Prompt injection · adversarial analysis · AI auditing'));
|
|
392
|
+
console.log();
|
|
393
|
+
console.log(chalk.bold.white(' How this differs from AI4CTF'));
|
|
394
|
+
console.log(chalk.gray(' · AI is your ') + chalk.red('target') + chalk.gray(', not your teammate'));
|
|
395
|
+
console.log(chalk.gray(' · Read the scenario carefully — rules vary'));
|
|
396
|
+
console.log(chalk.gray(' · Separate AI budget: ') + chalk.white('25,000 tokens'));
|
|
397
|
+
console.log();
|
|
398
|
+
console.log(chalk.yellow(' These are the hardest questions. Worth 21% of total score.'));
|
|
399
|
+
console.log(chalk.yellow(' If time is tight, skim Q39/40 first to decide attack order.'));
|
|
400
|
+
console.log(chalk.red(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
401
|
+
console.log();
|
|
402
|
+
shown.add('s_ctf4ai');
|
|
403
|
+
state.shownWarnings = Array.from(shown);
|
|
404
|
+
saveExamState(state);
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
340
408
|
function printQuestion(q, answer) {
|
|
341
409
|
const state = getExamState();
|
|
342
410
|
const total = Number(state?.session.questionCount || 30);
|
|
@@ -347,25 +415,9 @@ function printQuestion(q, answer) {
|
|
|
347
415
|
// Pacing hints (Q10 time check, Q30 section complete) — real exam only
|
|
348
416
|
if (state)
|
|
349
417
|
printPacingHint(state, q.number);
|
|
350
|
-
//
|
|
351
|
-
if (
|
|
352
|
-
|
|
353
|
-
console.log();
|
|
354
|
-
console.log(chalk.cyan(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
355
|
-
console.log(chalk.bold.white(' Practical Section — Python Required'));
|
|
356
|
-
console.log(chalk.cyan(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
357
|
-
console.log();
|
|
358
|
-
console.log(chalk.white(' Three ways to run Python:'));
|
|
359
|
-
console.log();
|
|
360
|
-
console.log(chalk.yellow(' 1.') + chalk.white(' One-liner: ') + chalk.green('!python3 -c "print(1+1)"'));
|
|
361
|
-
console.log(chalk.yellow(' 2.') + chalk.white(' Interactive: ') + chalk.green('!python3') + chalk.gray(' → >>> import struct ...'));
|
|
362
|
-
console.log(chalk.yellow(' 3.') + chalk.white(' Script: ') + chalk.green("!cat << 'EOF' > s.py") + chalk.gray(' → ') + chalk.green('!python3 s.py'));
|
|
363
|
-
console.log();
|
|
364
|
-
console.log(chalk.white(' Need help? Type ') + chalk.bold.cyan('hint') + chalk.white(' to ask AI (25K tokens per section)'));
|
|
365
|
-
console.log(chalk.white(' Submit flag: ') + chalk.green('exam answer <n> ICOA{your_flag}'));
|
|
366
|
-
console.log(chalk.cyan(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
367
|
-
console.log();
|
|
368
|
-
}
|
|
418
|
+
// Section intros (AI4CTF at Q31, CTF4AI at Q39) — real exam only
|
|
419
|
+
if (state && isPractical)
|
|
420
|
+
printSectionIntro(state, q.number);
|
|
369
421
|
// Urgent countdown warnings (10 / 5 / 1 minutes remaining)
|
|
370
422
|
if (state)
|
|
371
423
|
printTimeWarningIfNeeded(state);
|