forked from 1c-syntax/bsl-language-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Реализация правила + тесты + precommit
- Loading branch information
Showing
8 changed files
with
384 additions
and
0 deletions.
There are no files selected for viewing
57 changes: 57 additions & 0 deletions
57
docs/diagnostics/DisableSafeModeForExternalDataProcessors.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Отключение безопасного режима во внешних обработках, отчетах для БСП (DisableSafeModeForExternalDataProcessors) | ||
|
||
<!-- Блоки выше заполняются автоматически, не трогать --> | ||
|
||
## Описание диагностики | ||
|
||
<!-- Описание диагностики заполняется вручную. Необходимо понятным языком описать смысл и схему работу --> | ||
Помимо программного кода конфигурации, в прикладном решении может исполняться сторонний программный код, который может | ||
быть подключен с помощью внешних отчетов, внешних обработок, расширений конфигурации, внешних компонент или другими | ||
способами, например, с помощью стороннего (по отношению к конфигурации) программного кода, надежность которого | ||
разработчик гарантировать не может (далее – внешний код). При этом злоумышленник может предусмотреть в нем различные | ||
деструктивные действия (как в самом внешнем коде, так и опосредовано, через запуск внешних приложений, внешних | ||
компонент, COM-объектов), которые могут нанести вред компьютерам пользователей, серверным компьютерам, а также данным в | ||
программе. | ||
|
||
Перечисленные проблемы безопасности особенно критичны при работе конфигураций в модели сервиса. Например, получив доступ | ||
к сервису, вредоносный код может получить доступ сразу ко всем приложениям всех пользователей сервиса. | ||
|
||
Поэтому важно контролировать выполнение подобного внешнего кода в безопасном режиме, в исключительных случаях точечно | ||
разрешая выполнять код в небезопасном режиме после верификации кода. | ||
|
||
Правило проверяет отключение безопасного режима во внешних отчетах и обработках, подключаемых к подсистеме " | ||
Дополнительные отчеты и обработки" для БСП-совместимых конфигураций. | ||
|
||
## Примеры | ||
|
||
<!-- В данном разделе приводятся примеры, на которые диагностика срабатывает, а также можно привести пример, как можно исправить ситуацию --> | ||
|
||
```bsl | ||
Функция СведенияОВнешнейОбработке() Экспорт | ||
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1"); | ||
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка(); | ||
ПараметрыРегистрации.БезопасныйРежим = Ложь; // будет выдано замечание | ||
ПараметрыРегистрации.БезопасныйРежим = Истина; // замечания не будет | ||
ПараметрыРегистрации.Вставить("БезопасныйРежим", Ложь); // будет выдано замечание | ||
ПараметрыРегистрации.Вставить("БезопасныйРежим", Истина); // замечания не будет | ||
Возврат ПараметрыРегистрации; | ||
КонецФункции | ||
``` | ||
|
||
## Источники | ||
|
||
<!-- Необходимо указывать ссылки на все источники, из которых почерпнута информация для создания диагностики --> | ||
<!-- Примеры источников | ||
* Источник: [Стандарт: Тексты модулей](https://its.1c.ru/db/v8std#content:456:hdoc) | ||
* Полезная информация: [Отказ от использования модальных окон](https://its.1c.ru/db/metod8dev#content:5272:hdoc) | ||
* Источник: [Cognitive complexity, ver. 1.4](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) --> | ||
|
||
- [Статья "Безопасный режим работы" - руководство разработчика 1С 8.3.22](https://its.1c.ru/db/v8322doc#bookmark:dev:TI000000186@ee788d9) | ||
- [Стандарт "Ограничение на выполнение «внешнего» кода"](https://its.1c.ru/db/v8std/content/669/hdoc) | ||
- [Стандарт "Безопасность прикладного программного интерфейса сервера"](https://its.1c.ru/db/v8std/content/678/hdoc) | ||
- [Стандарт "Ограничения на использование Выполнить и Вычислить на сервере"](https://its.1c.ru/db/v8std#content:770:hdoc) | ||
- [Стандарт Использование привилегированного режима](https://its.1c.ru/db/v8std/content/485/hdoc) |
20 changes: 20 additions & 0 deletions
20
docs/en/diagnostics/DisableSafeModeForExternalDataProcessors.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Disable safe mode for external data processors, reports for SSL (DisableSafeModeForExternalDataProcessors) | ||
|
||
<!-- Блоки выше заполняются автоматически, не трогать --> | ||
|
||
## Description | ||
|
||
<!-- Описание диагностики заполняется вручную. Необходимо понятным языком описать смысл и схему работу --> | ||
|
||
## Examples | ||
|
||
<!-- В данном разделе приводятся примеры, на которые диагностика срабатывает, а также можно привести пример, как можно исправить ситуацию --> | ||
|
||
## Sources | ||
|
||
<!-- Необходимо указывать ссылки на все источники, из которых почерпнута информация для создания диагностики --> | ||
<!-- Примеры источников | ||
* Источник: [Стандарт: Тексты модулей](https://its.1c.ru/db/v8std#content:456:hdoc) | ||
* Полезная информация: [Отказ от использования модальных окон](https://its.1c.ru/db/metod8dev#content:5272:hdoc) | ||
* Источник: [Cognitive complexity, ver. 1.4](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) --> |
222 changes: 222 additions & 0 deletions
222
...ax/bsl/languageserver/diagnostics/DisableSafeModeForExternalDataProcessorsDiagnostic.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
/* | ||
* This file is a part of BSL Language Server. | ||
* | ||
* Copyright (c) 2018-2023 | ||
* Alexey Sosnoviy <[email protected]>, Nikita Fedkin <[email protected]> and contributors | ||
* | ||
* SPDX-License-Identifier: LGPL-3.0-or-later | ||
* | ||
* BSL Language Server is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 3.0 of the License, or (at your option) any later version. | ||
* | ||
* BSL Language Server is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public | ||
* License along with BSL Language Server. | ||
*/ | ||
package com.github._1c_syntax.bsl.languageserver.diagnostics; | ||
|
||
import com.github._1c_syntax.bsl.languageserver.context.symbol.MethodSymbol; | ||
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticMetadata; | ||
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticScope; | ||
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticSeverity; | ||
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticTag; | ||
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticType; | ||
import com.github._1c_syntax.bsl.languageserver.references.ReferenceIndex; | ||
import com.github._1c_syntax.bsl.languageserver.utils.Ranges; | ||
import com.github._1c_syntax.bsl.parser.BSLParser; | ||
import com.github._1c_syntax.bsl.parser.BSLParserRuleContext; | ||
import com.github._1c_syntax.utils.CaseInsensitivePattern; | ||
import org.antlr.v4.runtime.tree.ParseTree; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.regex.Pattern; | ||
|
||
@DiagnosticMetadata( | ||
type = DiagnosticType.VULNERABILITY, | ||
severity = DiagnosticSeverity.MAJOR, | ||
minutesToFix = 5, | ||
tags = { | ||
DiagnosticTag.SUSPICIOUS | ||
}, | ||
scope = DiagnosticScope.BSL, | ||
activatedByDefault = true | ||
) | ||
|
||
public class DisableSafeModeForExternalDataProcessorsDiagnostic extends AbstractVisitorDiagnostic { | ||
|
||
public static final String MAIN_METHOD_NAME = "СведенияОВнешнейОбработке"; | ||
private static final String SAFE_MODE_PARAMETER = "БЕЗОПАСНЫЙРЕЖИМ"; | ||
private static final String SAFE_MODE_PARAMETER_WITH_QUOTES = "\"" + SAFE_MODE_PARAMETER + "\""; | ||
private static final Pattern INSERT_METHOD_PATTERN = CaseInsensitivePattern.compile("вставить|insert"); | ||
private final ReferenceIndex referenceIndex; | ||
private final Map<String, List<BSLParserRuleContext>> nodes = new HashMap<>(); | ||
private MethodSymbol methodSymbol; | ||
private Optional<String> mainCollection = Optional.empty(); | ||
|
||
public DisableSafeModeForExternalDataProcessorsDiagnostic(ReferenceIndex referenceIndex) { | ||
this.referenceIndex = referenceIndex; | ||
} | ||
|
||
private static boolean isFalseExpression(Optional<BSLParser.ExpressionContext> expressionContext) { | ||
return expressionContext | ||
.map(BSLParser.ExpressionContext::member) | ||
.filter(memberContexts -> !memberContexts.isEmpty()) | ||
.map(memberContexts -> memberContexts.get(0)) | ||
.map(BSLParser.MemberContext::constValue) | ||
.map(BSLParser.ConstValueContext::FALSE) | ||
.isPresent(); | ||
} | ||
|
||
private static boolean haveSafeModeText(BSLParser.CallParamContext callParamContext) { | ||
return Optional.of(callParamContext) | ||
.map(BSLParser.CallParamContext::expression) | ||
.map(BSLParser.ExpressionContext::member) | ||
.filter(memberContexts -> !memberContexts.isEmpty()) | ||
.map(memberContexts -> memberContexts.get(0)) | ||
.map(BSLParser.MemberContext::constValue) | ||
.map(BSLParser.ConstValueContext::string) | ||
.map(BSLParserRuleContext::getText) | ||
.filter(name -> name.equalsIgnoreCase(SAFE_MODE_PARAMETER_WITH_QUOTES)) | ||
.isPresent(); | ||
} | ||
|
||
@Override | ||
public ParseTree visitFile(BSLParser.FileContext ctx) { | ||
processFile(ctx); | ||
return null; | ||
|
||
} | ||
|
||
public void processFile(BSLParser.FileContext ctx) { | ||
final var mainMethodSymbol = getMainMethodSymbol(); | ||
if (mainMethodSymbol | ||
.isEmpty()) { | ||
return; | ||
} | ||
methodSymbol = mainMethodSymbol.get(); | ||
|
||
final var references = referenceIndex.getReferencesFrom(methodSymbol); | ||
if (references.isEmpty()) { | ||
return; | ||
} | ||
|
||
super.visitFile(ctx); // вычисляю имя возвращаемой переменной в mainCollectionName | ||
if (mainCollection.isPresent() && !nodes.isEmpty()) { | ||
nodes.get(mainCollection.get()) | ||
.forEach(diagnosticStorage::addDiagnostic); | ||
} | ||
} | ||
|
||
@NotNull | ||
private Optional<MethodSymbol> getMainMethodSymbol() { | ||
return documentContext.getSymbolTree().getMethodSymbol(MAIN_METHOD_NAME) | ||
.filter(MethodSymbol::isFunction) | ||
.filter(MethodSymbol::isExport); | ||
} | ||
|
||
@Override | ||
public ParseTree visitFunction(BSLParser.FunctionContext ctx) { | ||
// TODO проверить на вхождение range плюс или минус 1 | ||
if (Ranges.containsRange(methodSymbol.getRange(), Ranges.create(ctx)) && | ||
Optional.ofNullable(ctx.funcDeclaration()) | ||
.map(BSLParser.FuncDeclarationContext::subName) | ||
.map(BSLParser.SubNameContext::IDENTIFIER) | ||
.map(ParseTree::getText) | ||
.filter(s -> s.equalsIgnoreCase(MAIN_METHOD_NAME)) | ||
.isPresent()) { | ||
return super.visitFunction(ctx); | ||
} | ||
return null; // нет смысла анализировать другие методы | ||
} | ||
|
||
@Override | ||
public ParseTree visitProcedure(BSLParser.ProcedureContext ctx) { | ||
return null; // нет смысла анализировать другие методы | ||
} | ||
|
||
@Override | ||
public ParseTree visitReturnStatement(BSLParser.ReturnStatementContext ctx) { | ||
// TODO проверить на вхождение range плюс или минус 1 | ||
if (mainCollection.isEmpty() && Ranges.containsRange(methodSymbol.getRange(), Ranges.create(ctx))) { | ||
mainCollection = Optional.ofNullable(ctx.expression()) | ||
.map(BSLParser.ExpressionContext::member) | ||
.filter(memberContexts -> !memberContexts.isEmpty()) | ||
.map(memberContexts -> memberContexts.get(0)) | ||
.map(BSLParser.MemberContext::complexIdentifier) | ||
.map(BSLParser.ComplexIdentifierContext::IDENTIFIER) | ||
.map(ParseTree::getText); | ||
} | ||
return null; //нет смысла идти глубже | ||
} | ||
|
||
@Override | ||
public ParseTree visitAssignment(BSLParser.AssignmentContext ctx) { | ||
processAssignment(ctx); | ||
return null; // спускаться глубже нет смысла | ||
} | ||
|
||
public void processAssignment(BSLParser.AssignmentContext ctx) { | ||
final var lValueContext = Optional.of(ctx.lValue()); | ||
final var varName = lValueContext.map(BSLParser.LValueContext::IDENTIFIER) | ||
.map(ParseTree::getText); | ||
if (varName.isEmpty()) { | ||
return; | ||
} | ||
final var terminalNodeSafeMode = lValueContext | ||
.map(BSLParser.LValueContext::acceptor) | ||
.map(BSLParser.AcceptorContext::accessProperty) | ||
.map(BSLParser.AccessPropertyContext::IDENTIFIER) | ||
.filter(terminalNode1 -> terminalNode1.getText().equalsIgnoreCase(SAFE_MODE_PARAMETER)); | ||
|
||
if (terminalNodeSafeMode.isPresent() && isFalseExpression(Optional.ofNullable(ctx.expression()))) { | ||
nodes.computeIfAbsent(varName.get(), name -> new ArrayList<>()).add(ctx); | ||
} | ||
} | ||
|
||
@Override | ||
public ParseTree visitCallStatement(BSLParser.CallStatementContext ctx) { | ||
processCallStatement(ctx); | ||
return null; | ||
} | ||
|
||
public void processCallStatement(BSLParser.CallStatementContext ctx) { | ||
final var varName = Optional.ofNullable(ctx.IDENTIFIER()) | ||
.map(ParseTree::getText); | ||
if (varName.isEmpty()) { | ||
return; | ||
} | ||
|
||
final var methodCallContext = Optional.of(ctx) | ||
.map(BSLParser.CallStatementContext::accessCall) | ||
.map(BSLParser.AccessCallContext::methodCall); | ||
final var methodNameContext = methodCallContext | ||
.map(BSLParser.MethodCallContext::methodName) | ||
.filter(methodName -> INSERT_METHOD_PATTERN.matcher(methodName.getText()).matches()); | ||
if (methodNameContext.isEmpty()) { | ||
return; | ||
} | ||
final var expressionContext = methodCallContext | ||
.map(BSLParser.MethodCallContext::doCall) | ||
.map(BSLParser.DoCallContext::callParamList) | ||
.map(BSLParser.CallParamListContext::callParam) | ||
.filter(callParamContexts -> callParamContexts.size() == 2) | ||
.filter(callParamContexts -> haveSafeModeText(callParamContexts.get(0))) | ||
.map(callParamContexts -> callParamContexts.get(1)) | ||
.map(BSLParser.CallParamContext::expression); | ||
|
||
if (isFalseExpression(expressionContext)) { | ||
nodes.computeIfAbsent(varName.get(), name -> new ArrayList<>()).add(ctx); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
...nguageserver/diagnostics/DisableSafeModeForExternalDataProcessorsDiagnostic_en.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
diagnosticMessage=Check the safe mode setting | ||
diagnosticName=Disable safe mode for external data processors, reports for SSL |
2 changes: 2 additions & 0 deletions
2
...nguageserver/diagnostics/DisableSafeModeForExternalDataProcessorsDiagnostic_ru.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
diagnosticMessage=Проверьте отключение безопасного режима | ||
diagnosticName=Отключение безопасного режима во внешних обработках, отчетах для БСП |
46 changes: 46 additions & 0 deletions
46
...sl/languageserver/diagnostics/DisableSafeModeForExternalDataProcessorsDiagnosticTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* This file is a part of BSL Language Server. | ||
* | ||
* Copyright (c) 2018-2023 | ||
* Alexey Sosnoviy <[email protected]>, Nikita Fedkin <[email protected]> and contributors | ||
* | ||
* SPDX-License-Identifier: LGPL-3.0-or-later | ||
* | ||
* BSL Language Server is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 3.0 of the License, or (at your option) any later version. | ||
* | ||
* BSL Language Server is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public | ||
* License along with BSL Language Server. | ||
*/ | ||
package com.github._1c_syntax.bsl.languageserver.diagnostics; | ||
|
||
import org.eclipse.lsp4j.Diagnostic; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.util.List; | ||
|
||
import static com.github._1c_syntax.bsl.languageserver.util.Assertions.assertThat; | ||
|
||
class DisableSafeModeForExternalDataProcessorsDiagnosticTest extends AbstractDiagnosticTest<DisableSafeModeForExternalDataProcessorsDiagnostic> { | ||
DisableSafeModeForExternalDataProcessorsDiagnosticTest() { | ||
super(DisableSafeModeForExternalDataProcessorsDiagnostic.class); | ||
} | ||
|
||
@Test | ||
void test() { | ||
|
||
List<Diagnostic> diagnostics = getDiagnostics(); | ||
|
||
assertThat(diagnostics, true) | ||
.hasRange(5, 4, 47) | ||
.hasRange(7, 4, 58) | ||
.hasSize(2); | ||
} | ||
} |
Oops, something went wrong.