Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Правило "Запуск внешних приложений" - ExternalAppStarting #3115

Merged
merged 8 commits into from
Dec 26, 2023
78 changes: 78 additions & 0 deletions docs/diagnostics/ExternalAppStarting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Запуск внешних приложений (ExternalAppStarting)

<!-- Блоки выше заполняются автоматически, не трогать -->
## Описание диагностики
<!-- Описание диагностики заполняется вручную. Необходимо понятным языком описать смысл и схему работу -->
Для повышения качества и безопасности решения на 1С необходимо контролировать запуск внешних приложений из кода 1С.

Данное правило распространяется на все способы запуска внешних программ, в том числе:
- КомандаСистемы
- ЗапуститьСистему
- ЗапуститьПриложение
- НачатьЗапускПриложения
- ЗапуститьПриложениеАсинх
- ПерейтиПоНавигационнойСсылке или ФайловаяСистемаКлиент.ОткрытьНавигационнуюСсылку
- ФайловаяСистемаКлиент.ЗапуститьПрограмму (в клиентском коде) и ФайловаяСистема.ЗапуститьПрограмму (в серверном коде)
- ФайловаяСистемаКлиент.ОткрытьПроводник
- ФайловаяСистемаКлиент.ОткрытьФайл

## Примеры
<!-- В данном разделе приводятся примеры, на которые диагностика срабатывает, а также можно привести пример, как можно исправить ситуацию -->
```bsl
Процедура Метод()
СтрокаКоманды = "";
ТекущийКаталог = "";
ДождатьсяЗавершения = Истина;
ОписаниеОповещения = Неопределено;
ПараметрыКоманды = Новый Структура;

КомандаСистемы(СтрокаКоманды, ТекущийКаталог); // есть замечание
ЗапуститьПриложение(СтрокаКоманды, ТекущийКаталог); // есть замечание
ЗапуститьПриложение(СтрокаКоманды, ТекущийКаталог, Истина); // есть замечание

НачатьЗапускПриложения(ОписаниеОповещения, СтрокаКоманды, ТекущийКаталог, ДождатьсяЗавершения); // есть замечание

ПерейтиПоНавигационнойСсылке(СтрокаКоманды); // есть замечание
ФайловаяСистемаКлиент.ОткрытьНавигационнуюСсылку(СтрокаКоманды); // есть замечание
ФайловаяСистемаКлиент.ОткрытьНавигационнуюСсылку(СтрокаКоманды, ОписаниеОповещения); // есть замечание

ФайловаяСистемаКлиент.ЗапуститьПрограмму("ping 127.0.0.1 -n 5", ПараметрыКоманды); // есть замечание
ФайловаяСистемаКлиент.ЗапуститьПрограмму(СтрокаКоманды, ПараметрыКоманды); // есть замечание
ФайловаяСистема.ЗапуститьПрограмму(СтрокаКоманды); // есть замечание
ФайловаяСистема.ЗапуститьПрограмму(СтрокаКоманды, ПараметрыКоманды); // есть замечание

ФайловаяСистемаКлиент.ОткрытьПроводник("C:\Users"); // есть замечание
ФайловаяСистемаКлиент.ОткрытьФайл(СтрокаКоманды); // есть замечание
ФайловаяСистемаКлиент.ОткрытьФайл(СтрокаКоманды, ОписаниеОповещения); // есть замечание

КонецПроцедуры

&НаКлиенте
Асинх Процедура Подключить()
СтрокаКоманды = "";
ТекущийКаталог = "";
ДождатьсяЗавершения = Истина;

Ждать ЗапуститьПриложениеАсинх(СтрокаКоманды, ТекущийКаталог, ДождатьсяЗавершения); // есть замечание
КонецПроцедуры

&НаКлиенте
Процедура ПроверкаЗапуститьСистему(ДополнительныеПараметрыКоманднойСтроки, КодВозврата)
ДождатьсяЗавершения = Истина;

ЗапуститьСистему(); // есть замечание
ЗапуститьСистему(ДополнительныеПараметрыКоманднойСтроки); // есть замечание
ЗапуститьСистему(ДополнительныеПараметрыКоманднойСтроки, ДождатьсяЗавершения); // есть замечание
ЗапуститьСистему(ДополнительныеПараметрыКоманднойСтроки, ДождатьсяЗавершения, КодВозврата); // есть замечание
КонецПроцедуры
```

## Источники
<!-- Необходимо указывать ссылки на все источники, из которых почерпнута информация для создания диагностики -->
<!-- Примеры источников

* Источник: [Стандарт: Тексты модулей](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) -->
- [стандарт Безопасность запуска приложений](https://its.1c.ru/db/v8std/content/774/hdoc)
- [стандарт Ограничение на выполнение «внешнего» кода](https://its.1c.ru/db/v8std/content/669/hdoc )
16 changes: 16 additions & 0 deletions docs/en/diagnostics/ExternalAppStarting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# External applications starting (ExternalAppStarting)

<!-- Блоки выше заполняются автоматически, не трогать -->
## 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) -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* 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.diagnostics.metadata.DiagnosticMetadata;
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticParameter;
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.utils.CaseInsensitivePattern;

import java.util.Map;
import java.util.regex.Pattern;

@DiagnosticMetadata(
theshadowco marked this conversation as resolved.
Show resolved Hide resolved
type = DiagnosticType.VULNERABILITY,
severity = DiagnosticSeverity.MAJOR,
minutesToFix = 5,
tags = {
DiagnosticTag.SUSPICIOUS
},
scope = DiagnosticScope.BSL

)
public class ExternalAppStartingDiagnostic extends AbstractFindMethodDiagnostic {
private static final String DEFAULT_PATTERN_STRING =
"КомандаСистемы|System|ЗапуститьСистему|RunSystem|ЗапуститьПриложение|RunApp" +
"|НачатьЗапускПриложения|BeginRunningApplication" +
"|ЗапуститьПриложениеАсинх|RunAppAsync|ЗапуститьПрограмму|ОткрытьПроводник|ОткрытьФайл";
private static final String PATTERN_STRING_FOR_NAVI =
"|ПерейтиПоНавигационнойСсылке|GotoURL|ОткрытьНавигационнуюСсылку";
private static final Pattern DEFAULT_PATTERN = CaseInsensitivePattern.compile(DEFAULT_PATTERN_STRING);
private static final boolean CHECK_GOTO_URL = false;

@DiagnosticParameter(
type = Boolean.class,
defaultValue = "" + CHECK_GOTO_URL
)
private boolean checkGotoUrl = CHECK_GOTO_URL;

@DiagnosticParameter(
type = String.class,
defaultValue = DEFAULT_PATTERN_STRING
)
private String userPatternString = DEFAULT_PATTERN_STRING;

public ExternalAppStartingDiagnostic() {
super(DEFAULT_PATTERN);
}

@Override
public void configure(Map<String, Object> configuration) {
super.configure(configuration);
var pattern = userPatternString;
if (checkGotoUrl){
pattern += PATTERN_STRING_FOR_NAVI;
}
setMethodPattern(CaseInsensitivePattern.compile(pattern));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,30 @@
"title": "Ban export global module variables",
"$id": "#/definitions/ExportVariables"
},
"ExternalAppStarting": {
"description": "External applications starting",
"default": true,
"type": [
"boolean",
"object"
],
"title": "External applications starting",
"properties": {
"checkGotoUrl": {
"description": "Check navigation links",
"default": false,
"type": "boolean",
"title": "Check navigation links"
},
"userPatternString": {
"description": "User regex pattern",
"default": "\u041a\u043e\u043c\u0430\u043d\u0434\u0430\u0421\u0438\u0441\u0442\u0435\u043c\u044b|System|\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0421\u0438\u0441\u0442\u0435\u043c\u0443|RunSystem|\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435|RunApp|\u041d\u0430\u0447\u0430\u0442\u044c\u0417\u0430\u043f\u0443\u0441\u043a\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f|BeginRunningApplication|\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u0410\u0441\u0438\u043d\u0445|RunAppAsync|\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443|\u041e\u0442\u043a\u0440\u044b\u0442\u044c\u041f\u0440\u043e\u0432\u043e\u0434\u043d\u0438\u043a|\u041e\u0442\u043a\u0440\u044b\u0442\u044c\u0424\u0430\u0439\u043b",
"type": "string",
"title": "User regex pattern"
}
},
"$id": "#/definitions/ExternalAppStarting"
},
"ExtraCommas": {
"description": "Commas without a parameter at the end of a method call",
"default": true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
diagnosticMessage=Check the launch of an external application
diagnosticName=External applications starting
checkGotoUrl=Check navigation links
userPatternString=User regex pattern
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
diagnosticMessage=Проверьте запуск внешнего приложения
diagnosticName=Запуск внешних приложений
checkGotoUrl=Проверять переход по навигационным ссылкам
userPatternString=Пользовательский шаблон (регулярное выражение)
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* 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 java.util.Map;

import static com.github._1c_syntax.bsl.languageserver.util.Assertions.assertThat;

class ExternalAppStartingDiagnosticTest extends AbstractDiagnosticTest<ExternalAppStartingDiagnostic> {
ExternalAppStartingDiagnosticTest() {
super(ExternalAppStartingDiagnostic.class);
}

@Test
void test() {

List<Diagnostic> diagnostics = getDiagnostics();

assertThat(diagnostics, true)
.hasRange(8, 4, 18)
.hasRange(9, 4, 23)
.hasRange(10, 4, 23)
.hasRange(12, 4, 26)

.hasRange(18, 26, 44)
.hasRange(19, 26, 44)
.hasRange(20, 20, 38)
.hasRange(21, 20, 38)
.hasRange(23, 26, 42)
.hasRange(24, 26, 37)
.hasRange(25, 26, 37)
.hasRange(35, 10, 34)

.hasRange(53, 4, 20)
.hasRange(54, 4, 20)
.hasRange(55, 4, 20)
.hasRange(56, 4, 20)
.hasSize(16);
}

@Test
void testConfigure_checkGotoUrl() {

Map<String, Object> configuration = diagnosticInstance.info.getDefaultConfiguration();
configuration.put("checkGotoUrl", true);
diagnosticInstance.configure(configuration);

List<Diagnostic> diagnostics = getDiagnostics();

assertThat(diagnostics, true)
.hasRange(8, 4, 18)
.hasRange(9, 4, 23)
.hasRange(10, 4, 23)
.hasRange(12, 4, 26)

.hasRange(14, 4, 32)
.hasRange(15, 26, 52)
.hasRange(16, 26, 52)

.hasRange(18, 26, 44)
.hasRange(19, 26, 44)
.hasRange(20, 20, 38)
.hasRange(21, 20, 38)
.hasRange(23, 26, 42)
.hasRange(24, 26, 37)
.hasRange(25, 26, 37)
.hasRange(35, 10, 34)

.hasRange(53, 4, 20)
.hasRange(54, 4, 20)
.hasRange(55, 4, 20)
.hasRange(56, 4, 20)
.hasSize(19);
}

@Test
void testConfigure_userPatternString() {

Map<String, Object> configuration = diagnosticInstance.info.getDefaultConfiguration();
configuration.put("userPatternString", "КомандаСистемы");
diagnosticInstance.configure(configuration);

List<Diagnostic> diagnostics = getDiagnostics();

assertThat(diagnostics, true)
.hasRange(8, 4, 18)
.hasSize(1);
}

@Test
theshadowco marked this conversation as resolved.
Show resolved Hide resolved
void testConfigure_userPatternString_checkGotoUrl() {

Map<String, Object> configuration = diagnosticInstance.info.getDefaultConfiguration();
configuration.put("checkGotoUrl", true);
configuration.put("userPatternString", "КомандаСистемы");
diagnosticInstance.configure(configuration);

List<Diagnostic> diagnostics = getDiagnostics();

assertThat(diagnostics, true)
.hasRange(8, 4, 18)

.hasRange(14, 4, 32)
.hasRange(15, 26, 52)
.hasRange(16, 26, 52)

.hasSize(4);
}
}
Loading
Loading