@@ -20,68 +20,132 @@ function parseJsonObject(value) {
2020
2121function buildAiPrompt ( { targetType, targetUrl, sourceKind, level, findings, vulnerabilities, toolsUsed, artifact, datasetExamples, language = "ru" } ) {
2222 return [
23- 'Ты — senior аудитор смарт-контрактов. Пиши на русском. Изучи базу знаний ниже .' ,
23+ 'Ты — senior аудитор смарт-контрактов с 10-летним опытом работы в Web3 security .' ,
2424 '' ,
25- '=== БАЗА ЗНАНИЙ: РЕАЛЬНЫЕ ЭКСПЛОЙТЫ ===' ,
25+ '=== РЕАЛЬНЫЕ ЭКСПЛОЙТЫ С ПРИМЕРАМИ КОДА ===' ,
2626 '' ,
27- 'REENTRANCY:' ,
28- '- The DAO (2016, $60M): fallback() вызвал withdraw() повторно до обновления баланса' ,
29- '- Cream Finance (2021, $130M): reentrancy через токен ERC-777' ,
30- '- Fei Protocol (2022, $80M): reentrancy через flashloan + deposit' ,
31- '- Исправление: использовать ReentrancyGuard или CEI (Checks-Effects-Interactions)' ,
27+ '1. REENTRANCY (The DAO, 2016, $60M):' ,
28+ ' УЯЗВИМЫЙ КОД:' ,
29+ ' ```solidity' ,
30+ ' function withdraw(uint _amount) public {' ,
31+ ' require(balances[msg.sender] >= _amount);' ,
32+ ' msg.sender.call{value: _amount}(""); // ВНЕШНИЙ ВЫЗОВ ДО ОБНОВЛЕНИЯ' ,
33+ ' balances[msg.sender] -= _amount;' ,
34+ ' }' ,
35+ ' ```' ,
36+ ' ИСПРАВЛЕНИЕ:' ,
37+ ' ```solidity' ,
38+ ' function withdraw(uint _amount) public {' ,
39+ ' require(balances[msg.sender] >= _amount);' ,
40+ ' balances[msg.sender] -= _amount; // СНАЧАЛА ОБНОВЛЕНИЕ' ,
41+ ' (bool success,) = msg.sender.call{value: _amount}("");' ,
42+ ' require(success, "Transfer failed");' ,
43+ ' }' ,
44+ ' ```' ,
3245 '' ,
33- 'ACCESS CONTROL:' ,
34- '- Poly Network (2021, $600M): отсутствие проверки прав на вызов функции' ,
35- '- Wormhole (2022, $325M): отсутствие валидации guardian подписей' ,
36- '- Qubit Finance (2022, $80M): устаревшая функция без модификатора' ,
37- '- Исправление: onlyOwner, RBAC, multi-sig, временные блокировки' ,
46+ '2. ACCESS CONTROL (Poly Network, 2021, $600M):' ,
47+ ' УЯЗВИМЫЙ КОД: function mint(address to, uint amount) public { _mint(to, amount); }' ,
48+ ' ИСПРАВЛЕНИЕ: function mint(address to, uint amount) public onlyOwner { _mint(to, amount); }' ,
3849 '' ,
39- 'DELEGATECALL:' ,
40- '- Parity Wallet (2017, $150M): delegatecall в незащищённую библиотеку с selfdestruct' ,
41- '- Исправление: использовать immutable для адреса библиотеки, проверять код' ,
50+ '3. INTEGER OVERFLOW (BeautyChain BEC, 2018, $900M):' ,
51+ ' УЯЗВИМЫЙ КОД:' ,
52+ ' ```solidity' ,
53+ ' function batchTransfer(address[] _receivers, uint256 _value) public {' ,
54+ ' uint256 amount = _receivers.length * _value; // ПЕРЕПОЛНЕНИЕ' ,
55+ ' require(balances[msg.sender] >= amount);' ,
56+ ' balances[msg.sender] -= amount;' ,
57+ ' }' ,
58+ ' ```' ,
59+ ' ИСПРАВЛЕНИЕ:' ,
60+ ' ```solidity' ,
61+ ' using SafeMath for uint256;' ,
62+ ' function batchTransfer(address[] _receivers, uint256 _value) public {' ,
63+ ' uint256 amount = _receivers.length.mul(_value); // БЕЗОПАСНО' ,
64+ ' require(balances[msg.sender] >= amount);' ,
65+ ' balances[msg.sender] = balances[msg.sender].sub(amount);' ,
66+ ' }' ,
67+ ' ```' ,
4268 '' ,
43- 'INTEGER OVERFLOW:' ,
44- '- PoWH Coin (2018): арифметическое переполнение через оператор сложения-присваивания' ,
45- '- BeautyChain (2018): переполнение uint256 через умножение' ,
46- '- Исправление: Solidity 0.8+ или SafeMath библиотека' ,
69+ '4. DELEGATECALL (Parity Wallet, 2017, $150M):' ,
70+ ' УЯЗВИМЫЙ КОД:' ,
71+ ' ```solidity' ,
72+ ' address lib = 0x...;' ,
73+ ' (bool success,) = lib.delegatecall(data); // НЕПРОВЕРЕННЫЙ БИБЛИОТЕКА' ,
74+ ' ```' ,
75+ ' ИСПРАВЛЕНИЕ:' ,
76+ ' ```solidity' ,
77+ ' address immutable lib = 0x...; // immutable АДРЕС' ,
78+ ' require(isValidLibrary(lib), "Invalid library");' ,
79+ ' (bool success,) = lib.delegatecall(data);' ,
80+ ' require(success, "Delegatecall failed");' ,
81+ ' ```' ,
4782 '' ,
48- 'ORACLE/MANIPULATION:' ,
49- '- Inverse Finance (2022, $15M): манипуляция ценовым оракулом через flashloan' ,
50- '- Cream Finance (2021): манипуляция ценой через низколиквидный пул' ,
51- '- Исправление: TWAP (средневзвешенная цена), множественные источники цен' ,
83+ '5. UNCHECKED CALL (Lendf.Me, 2020, $25M):' ,
84+ ' УЯЗВИМЫЙ КОД: (bool success,) = addr.call{value: amount}("");' ,
85+ ' ИСПРАВЛЕНИЕ:' ,
86+ ' ```solidity' ,
87+ ' (bool success,) = addr.call{value: amount}("");' ,
88+ ' require(success, "ETH transfer failed");' ,
89+ ' ```' ,
5290 '' ,
53- 'FLASHLOAN ATTACKS:' ,
54- '- PancakeBunny (2021, $200M): манипуляция ценой через flashloan + mint' ,
55- '- Harvest Finance (2020, $33M): flashloan для арбитража кривой' ,
56- '- Исправление: проверка slippage, минимальное время между действиями' ,
91+ '6. FRONT-RUNNING (Bancor, 2020):' ,
92+ ' УЯЗВИМЫЙ КОД:' ,
93+ ' ```solidity' ,
94+ ' function swap(uint amount) public {' ,
95+ ' require(balances[msg.sender] >= amount); // ПРОВЕРКА' ,
96+ ' uint price = getPrice(); // ЦЕНА МОЖЕТ ИЗМЕНИТЬСЯ' ,
97+ ' balances[msg.sender] -= amount; // ОБНОВЛЕНИЕ ПОЗДНО' ,
98+ ' }' ,
99+ ' ```' ,
100+ ' ИСПРАВЛЕНИЕ:' ,
101+ ' ```solidity' ,
102+ ' function swap(uint amount, uint minOut) public {' ,
103+ ' require(balances[msg.sender] >= amount);' ,
104+ ' balances[msg.sender] -= amount; // СНАЧАЛА ОБНОВЛЕНИЕ' ,
105+ ' uint price = getPrice();' ,
106+ ' require(price >= minOut, "Slippage too high");' ,
107+ ' }' ,
108+ ' ```' ,
57109 '' ,
58- 'UNCHECKED RETURN VALUES:' ,
59- '- Lendf.Me (2020, $25M): не проверен результат .call()' ,
60- '- Исправление: require(success, "Call failed")' ,
110+ '=== ВАЖНЫЕ ПРАВИЛА АУДИТА ===' ,
61111 '' ,
62- 'FRONT-RUNNING:' ,
63- '- Bancor (2020): фронт-раннинг через публичный mempool' ,
64- '- Исправление: commit-reveal схема, лимит slippage' ,
112+ '1. Checks-Effects-Interactions: Всегда обновляй состояние ДО внешних вызовов' ,
113+ '2. Используй OpenZeppelin контракты (ReentrancyGuard, Ownable, SafeMath)' ,
114+ '3. Не доверяй tx.origin, используй msg.sender' ,
115+ '4. Проверяй возвращаемые значения низкоуровневых call' ,
116+ '5. Для дедлайнов используй блоки (block.timestamp + 30min buffer)' ,
117+ '6. Добавляй zero-address проверки для всех трансферов' ,
118+ '7. Используй immutable для неизменяемых адресов' ,
65119 '' ,
66- 'LOGIC ERRORS:' ,
67- '- bZx (2020, $8M): логическая ошибка в проверке состояния' ,
68- '- Yearn Finance (2021, $11M): ошибка в расчёте доли' ,
69- '- Исправление: тщательное тестирование, формальная верификация' ,
120+ '=== ТВОЯ ЗАДАЧА ===' ,
70121 '' ,
71- '=== ЗАДАЧА ===' ,
72- 'Проанализируй находки ниже и для каждой:' ,
73- '1. Конкретный уязвимый код из контракта' ,
74- '2. Исправленный код (Solidity)' ,
75- '3. Сценарий атаки с суммой потенциального ущерба' ,
76- '4. Вероятность эксплуатации (Low/Medium/High)' ,
77- '5. Похожий реальный эксплойт из базы знаний' ,
122+ 'Проанализируй находки детекторов ниже и сгенерируй JSON отчёт.' ,
78123 '' ,
79- 'Формат: JSON с ключами executiveSummary, criticalRisks, remediationRoadmap, trainingSignals' ,
80- 'Пиши ТОЛЬКО на русском. Никаких общих фраз.' ,
124+ 'ТРЕБОВАНИЯ К ОТВЕТУ:' ,
125+ '- executiveSummary: 2-3 предложения, укажи общий риск (Low/Medium/High/Critical)' ,
126+ '- criticalRisks: массив строк, КАЖДАЯ строка содержит (1) описание уязвимости, (2) ссылку на реальный эксплойт, (3) пример суммы ущерба' ,
127+ '- remediationRoadmap: массив строк, КАЖДАЯ строка содержит (1) что исправить, (2) КОНКРЕТНЫЙ КОД исправления (Solidity)' ,
128+ '- trainingSignals: массив строк, 2-3 предложения как улучшить автоматическое обнаружение' ,
81129 '' ,
82- `Контракт: ${ targetUrl || 'артефакт' } (${ targetType } , ${ sourceKind } )` ,
83- `Уровень: ${ level } | Risk Score: ${ vulnerabilities ?. riskScore || 'N/A' } /100` ,
84- `Находки: ${ JSON . stringify ( ( findings || [ ] ) . slice ( 0 , 25 ) ) } ` ,
130+ 'ФОРМАТ ОТВЕТА - ТОЛЬКО JSON, НИКАКОГО ДРУГОГО ТЕКСТА:' ,
131+ '{' ,
132+ ' "executiveSummary": "string",' ,
133+ ' "criticalRisks": ["string", "string"],' ,
134+ ' "remediationRoadmap": ["string", "string"],' ,
135+ ' "trainingSignals": ["string", "string"]' ,
136+ '}' ,
137+ '' ,
138+ `=== ДАННЫЕ ДЛЯ АНАЛИЗА ===` ,
139+ `Тип цели: ${ targetType } ` ,
140+ `Цель: ${ targetUrl || 'загруженный контракт' } ` ,
141+ `Тип исходного кода: ${ sourceKind } ` ,
142+ `Уровень сканирования: ${ level } ` ,
143+ `Оценка риска: ${ vulnerabilities ?. riskScore || 'N/A' } /100` ,
144+ `Инструменты: ${ JSON . stringify ( toolsUsed || [ 'chainscout' ] ) } ` ,
145+ `Находки детекторов (${ findings ?. length || 0 } ):` ,
146+ `${ JSON . stringify ( ( findings || [ ] ) . slice ( 0 , 30 ) , null , 2 ) } ` ,
147+ '' ,
148+ 'ВНИМАНИЕ: remediationRoadmap ДОЛЖЕН содержать примеры кода. Никаких общих фраз типа "убедитесь в безопасности".' ,
85149 ] . join ( '\n' ) ;
86150}
87151
@@ -91,11 +155,12 @@ async function getOpenRouterAiAnalysis({ prompt, maxTokens }) {
91155 messages : [
92156 {
93157 role : 'system' ,
94- content : 'Ты — senior Web3 аудитор. Пиши на русском. Даёшь КОНКРЕТНЫЕ исправления с ПРИМЕРАМИ КОДА Solidity/Rust. Никаких общих советов — только точный код .' ,
158+ content : 'Ты — senior Web3 аудитор. Отвечаешь ТОЛЬКО валидным JSON. remediationRoadmap обязательно содержит конкретный код Solidity. Никогда не используй общие советы без примеров кода .' ,
95159 } ,
96160 { role : 'user' , content : prompt } ,
97161 ] ,
98162 maxTokens,
163+ temperature : 0.3 ,
99164 } ) ;
100165 const content = response ?. choices ?. [ 0 ] ?. message ?. content || response ?. output ?. [ 0 ] ?. content || '' ;
101166 return parseJsonObject ( String ( content ) ) ;
@@ -108,12 +173,12 @@ async function getOpenAIAiAnalysis({ prompt, maxTokens }) {
108173 messages : [
109174 {
110175 role : 'system' ,
111- content : 'You are a senior Web3 security auditor. You provide SPECIFIC, ACTIONABLE recommendations with code examples.' ,
176+ content : 'You are a senior Web3 security auditor. Return ONLY valid JSON. remediationRoadmap MUST contain concrete Solidity code examples.' ,
112177 } ,
113178 { role : 'user' , content : prompt } ,
114179 ] ,
115180 max_tokens : maxTokens ,
116- temperature : 0.2 ,
181+ temperature : 0.3 ,
117182 } , {
118183 headers : { Authorization : `Bearer ${ OPENAI_API_KEY } ` , 'Content-Type' : 'application/json' } ,
119184 timeout : 25000 ,
@@ -124,7 +189,7 @@ async function getOpenAIAiAnalysis({ prompt, maxTokens }) {
124189
125190async function generateAiAnalysis ( { targetType, targetUrl, sourceKind, level, findings, vulnerabilities, toolsUsed, artifact, datasetExamples } ) {
126191 const prompt = buildAiPrompt ( { targetType, targetUrl, sourceKind, level, findings, vulnerabilities, toolsUsed, artifact, datasetExamples } ) ;
127- const maxTokens = 2000 ;
192+ const maxTokens = 2500 ;
128193
129194 if ( process . env . OPENROUTER_API_KEY ) {
130195 try {
0 commit comments