Exemple #1
0
    def to_violation(self, result: Dict[str, Any]) -> Violation:
        path = self.trim_base(result["path"])
        abspath = self.base_path / path

        check_id = str(result["code"])
        line = result["line"]
        return Violation(
            tool_id=PyreTool.TOOL_ID,
            check_id=check_id,
            path=path,
            line=line,
            column=result["column"],
            message=result["description"],
            severity=2,
            syntactic_context=fetch_line_in_file(abspath, line)
            or "<no source found>",
            link="https://pyre-check.org/docs/error-types.html",
        )
Exemple #2
0
    def parse(self, tool_output: str) -> List[Violation]:
        results = json.loads(tool_output)

        violations = [
            Violation(
                check_id=r["code"].replace(self.CHECK_PREFIX, ""),
                tool_id=JinjalintTool.TOOL_ID,
                path=self.trim_base(r["file_path"]),
                severity=JinjalintParser.SEVERITY["MEDIUM"],
                line=r["line"],
                column=r["column"],
                message=r["message"],
                syntactic_context=r.get("physical_line", ""),
                link=self._get_link(r["code"]),
            ) for r in results
        ]

        return violations
Exemple #3
0
    def to_violation(self, result: Dict[str, Any]) -> Violation:
        source = (result["physical_line"]
                  or "").rstrip()  # Remove trailing whitespace
        path = self.trim_base(result["filename"])

        check_id = result["code"]

        return Violation(
            tool_id=self.tool().tool_id(),
            check_id=self.id_to_name(check_id),
            path=path,
            line=result["line_number"],
            column=result["column_number"],
            message=result["text"],
            severity=2,
            syntactic_context=source,
            link=self.id_to_link(check_id),
        )
Exemple #4
0
 def to_violation(self, output_rule: Dict[str, Any]) -> Violation:
     output = output_rule["output"]
     check_id = output_rule["id"]
     message = output_rule.get("message")
     parts = output.split(":")
     path = parts[0]
     path = self.trim_base(path)
     line_no = int(parts[1])
     code_snippet = ":".join(parts[2:])
     return Violation(
         tool_id=GrepTool.TOOL_ID,
         check_id=check_id,
         path=path,
         line=line_no,
         column=1,
         message=message or code_snippet,
         severity=2,
         syntactic_context=code_snippet or "<no context>",
     )
Exemple #5
0
def test_run(tmp_path: Path) -> None:
    tool = DlintTool(context_for(tmp_path, DlintTool.TOOL_ID, SIMPLE_INTEGRATION_PATH))
    tool.setup()
    violations = tool.results(SIMPLE_TARGETS)

    expectation = [
        Violation(
            check_id="regular-expression-catastrophic-backtracking",
            tool_id=DlintTool.TOOL_ID,
            path="baz.py",
            line=4,
            column=0,
            message='catastrophic "re" usage - denial-of-service possible',
            severity=2,
            syntactic_context="re.search(r'(a+)+b', 'TEST')",
            link="https://github.com/dlint-py/dlint/blob/master/docs/linters/DUO138.md",
        )
    ]
    assert violations == expectation
Exemple #6
0
    def parse(self, tool_output: str) -> List[Violation]:
        results = json.loads(tool_output)

        violations = [
            Violation(
                check_id=DLINT_TO_BENTO[result["code"]],
                tool_id=DlintTool.TOOL_ID,
                path=self.trim_base(filename),
                severity=DlintParser.SEVERITY["MEDIUM"],
                line=result["line_number"],
                column=result["column_number"],
                message=result["text"],
                syntactic_context=(result["physical_line"] or "").rstrip(),
                link=self._get_link(result["code"]),
            ) for filename, file_results in results.items()
            for result in file_results
        ]

        return violations
Exemple #7
0
    def to_violation(self, result: Dict[str, Any]) -> Violation:
        start_line = result["line"]
        column = result["column"]
        check_id = result["code"]
        message = result["message"]
        path = result["file"]

        path = self.trim_base(path)

        level = result["level"]
        if level == "error":
            severity = 2
        elif level == "warning":
            severity = 1
        elif level == "info":
            severity = 0
        elif level == "style":
            severity = 0

        if "DL" in check_id or check_id in ["SC2046", "SC2086"]:
            link = f"https://github.com/hadolint/hadolint/wiki/{check_id}"
        elif "SC" in check_id:
            link = f"https://github.com/koalaman/shellcheck/wiki/{check_id}"
        else:
            link = ""

        line_of_code = (fetch_line_in_file(self.base_path / path, start_line)
                        or "<no source found>")

        if check_id == "DL1000":
            message = "Dockerfile parse error. Invalid docker instruction."

        return Violation(
            tool_id=HadolintTool.TOOL_ID,
            check_id=check_id,
            path=path,
            line=start_line,
            column=column,
            message=message,
            severity=severity,
            syntactic_context=line_of_code,
            link=link,
        )
Exemple #8
0
def test_run(tmp_path: Path) -> None:
    base_path = BASE_PATH / "tests" / "integration" / "go"
    tool = GosecTool(context_for(tmp_path, GosecTool.tool_id(), base_path))
    tool.setup()
    violations = tool.results([base_path / "bad.go"])
    assert violations == [
        Violation(
            tool_id="gosec",
            check_id="G101",
            path="bad.go",
            line=7,
            column=2,
            message="Potential hardcoded credentials",
            severity=2,
            syntactic_context=
            'password := "******"\n',
            filtered=None,
            link="https://cwe.mitre.org/data/definitions/798.html",
        )
    ]
Exemple #9
0
def test_parse() -> None:
    with (THIS_PATH / "flake8_violation_simple.json").open() as json_file:
        json = json_file.read()

    result = Flake8Parser(BASE_PATH).parse(json)

    expectation = [
        Violation(
            tool_id="flake8",
            check_id="E124",
            path="foo.py",
            line=2,
            column=0,
            message="closing bracket does not match visual indentation",
            severity=2,
            syntactic_context="        )",
        )
    ]

    assert result == expectation
Exemple #10
0
    def parse(self, results: JsonR) -> List[Violation]:
        violations: List[Violation] = []
        for check in results:
            path = self.trim_base(check["path"])
            start_line = check["start"]["line"]
            start_col = check["start"]["col"]
            check_id = check["check_id"]

            violation = Violation(
                tool_id=CheckedReturnTool.tool_id(),
                check_id=check_id,
                path=path,
                line=start_line,
                column=start_col,
                message=check.get("extra", {}).get("message"),
                severity=2,
                syntactic_context=check.get("extra", {}).get("line"),
            )

            violations.append(violation)
        return violations
Exemple #11
0
def test_run(tmp_path_factory: tmp_path_factory) -> None:
    base_path = BASE_PATH / "tests/integration/python_taint"
    tool = PythonTaintTool(
        context_for(tmp_path_factory, PythonTaintTool.tool_id(), base_path))
    tool.setup()
    violations = tool.results()
    expectation = [
        Violation(
            tool_id="PythonTaint",
            check_id="5001: Possible shell injection",
            path="source.py",
            line=13,
            column=22,
            message=
            "Possible shell injection [5001]: Data from [UserControlled] source(s) may reach [RemoteCodeExecution] sink(s)",
            severity=2,
            syntactic_context="    image = get_image(image_link)\n",
        )
    ]

    assert violations == expectation
Exemple #12
0
def test_run_flask_violations(tmp_path: Path) -> None:
    tool = Boto3Tool(context_for(tmp_path, Boto3Tool.TOOL_ID, BOTO3_INTEGRATION_PATH))
    tool.setup()
    violations = tool.results(BOTO3_TARGETS)

    expectation = [
        Violation(
            tool_id="r2c.boto3",
            check_id="hardcoded-access-token",
            path="bad.py",
            line=4,
            column=11,
            message="Hardcoded access token detected. Consider using a config file or environment variables.",
            severity=2,
            syntactic_context="session = Session(aws_access_key_id='AKIA1235678901234567',",
            filtered=None,
            link="https://checks.bento.dev/en/latest/flake8-boto3/hardcoded-access-token",
        )
    ]

    assert violations == expectation
def test_run(tmp_path: Path) -> None:
    base_path = BASE_PATH / "tests/integration/checked_return"
    tool = CheckedReturnTool(
        context_for(tmp_path, CheckedReturnTool.tool_id(), base_path)
    )
    tool.setup()
    violations = tool.results([base_path / "checkedreturn.js"])
    expectation = [
        Violation(
            tool_id="r2c.checked_return",
            check_id="checked_return",
            path="checkedreturn.js",
            line=25,
            column=3,
            message="./checkedreturn.js:25:2: error unchecked return for must_be_used (used = 11, ignored = 1)",
            severity=2,
            syntactic_context="  must_be_used(); //maybe a bug, but not counted for now, maybe used for its throwing effect",
        )
    ]

    assert violations == expectation
Exemple #14
0
def test_missing_source() -> None:
    with (THIS_PATH /
          "eslint_violation_missing_source.json").open() as json_file:
        json_data = json_file.read()

    result = EslintParser(BASE_PATH).parse(json.loads(json_data))

    expectation = [
        Violation(
            tool_id="r2c.eslint",
            check_id="no-console",
            path="tests/integration/simple/init.js",
            line=0,
            column=0,
            message="Unexpected console statement.",
            severity=1,
            syntactic_context="",
        )
    ]

    assert result == expectation
Exemple #15
0
def test_run_flask_violations(tmp_path: Path) -> None:
    base_path = BASE_PATH / "tests/integration/flask"
    tool = FlaskTool(context_for(tmp_path, FlaskTool.TOOL_ID, base_path))
    tool.setup()
    violations = tool.results([base_path / "bad.py"])

    expectation = [
        Violation(
            tool_id="r2c.flask",
            check_id="send-file-open",
            path="bad.py",
            line=4,
            column=1,
            message="Passing a file-like object to flask.send_file without the mimetype or attachment_filename keyword arg will raise a ValueError. If you are sending a static file, pass in a string path to the file instead. Otherwise, specify a mimetype or attachment_filename in flask.send_file.",
            severity=2,
            syntactic_context='flask.send_file(open("file.txt"))',
            filtered=None,
            link="https://bento.dev/checks/en/latest/flake8-flask/send-file-open",
        )
    ]

    assert violations == expectation
Exemple #16
0
def test_parse() -> None:
    with (THIS_PATH / "boto3_violation_simple.json").open() as json_file:
        json = json_file.read()

    result = Boto3Parser(BASE_PATH).parse(json)

    expectation = [
        Violation(
            tool_id="r2c.boto3",
            check_id="hardcoded-access-token",
            path="bad.py",
            line=4,
            column=1,
            message="Hardcoded access token detected. Consider using a config file or environment variables.",
            severity=2,
            syntactic_context="Session(aws_access_key_id='AKIA1235678901234567',",
            filtered=None,
            link="https://checks.bento.dev/en/latest/flake8-boto3/hardcoded-access-token",
        )
    ]

    assert result == expectation
Exemple #17
0
def test_parse() -> None:
    with (THIS_PATH / "flask_violation_simple.json").open() as json_file:
        json = json_file.read()

    result = FlaskParser(BASE_PATH).parse(json)

    expectation = [
        Violation(
            tool_id="r2c.flask",
            check_id="send-file-open",
            path="bad.py",
            line=4,
            column=1,
            message="Passing a file-like object to flask.send_file without the mimetype or attachment_filename keyword arg will raise a ValueError. If you are sending a static file, pass in a string path to the file instead. Otherwise, specify a mimetype or attachment_filename in flask.send_file.",
            severity=2,
            syntactic_context='flask.send_file(open("file.txt"))',
            filtered=None,
            link="https://bento.dev/checks/en/latest/flake8-flask/send-file-open",
        )
    ]

    assert result == expectation
def test_run(tmp_path: Path) -> None:
    tool = PythonTaintTool(
        context_for(tmp_path, PythonTaintTool.tool_id(),
                    TAINT_INTEGRATION_PATH))
    tool.setup()
    violations = tool.results(TAINT_TARGETS)

    expectation = [
        Violation(
            tool_id="PythonTaint",
            check_id="5001: Possible shell injection",
            path="source.py",
            line=13,
            column=22,
            message=
            "Possible shell injection [5001]: Data from [UserControlled] source(s) may reach [RemoteCodeExecution] sink(s)",
            severity=2,
            syntactic_context="    image = get_image(image_link)\n",
        )
    ]

    assert violations == expectation
Exemple #19
0
    def parse(self, results: JsonR) -> List[Violation]:
        violations: List[Violation] = []
        for check in results:
            path = self.trim_base(check["path"])
            start_line = check["start"]["line"]
            start_col = check["start"]["col"]
            # Custom way to get check_name for sgrep-lint:0.1.10
            message = check.get("extra", {}).get("message")
            check_name, message = message.split(":")
            violation = Violation(
                tool_id=SGrepTool.tool_id(),
                check_id=check_name,
                path=path,
                line=start_line,
                column=start_col,
                message=message,
                severity=2,
                syntactic_context=check.get("extra", {}).get("line"),
            )

            violations.append(violation)
        return violations
Exemple #20
0
    def parse(self, results: JsonR) -> List[Violation]:
        violations: List[Violation] = []
        for check in results:
            path = self.trim_base(check["path"])
            start_line = check["start"]["line"]
            start_col = check["start"]["col"]
            check_id = check["check_id"]

            line_of_code = (fetch_line_in_file(
                self.base_path / path, start_line) or "<no source found>")

            violation = Violation(
                tool_id=PythonTaintTool.tool_id(),
                check_id=check_id,
                path=path,
                line=start_line,
                column=start_col,
                message=check.get("extra", {}).get("description"),
                severity=2,
                syntactic_context=line_of_code,
            )

            violations.append(violation)
        return violations
Exemple #21
0
    def parse(self, results: JsonR) -> List[Violation]:
        violations: List[Violation] = []
        for check in results:
            check_id = check["check_id"]
            path = self.trim_base(check["path"])
            start_line = check["start"]["line"]
            start_col = check["start"]["col"]
            # Custom way to get check_name for sgrep-lint:0.1.10
            message = check.get("extra", {}).get("message")
            source = (fetch_line_in_file(self.base_path / path, start_line)
                      or "<no source found>").rstrip()
            violation = Violation(
                tool_id=self.tool_id(),
                check_id=check_id,
                path=path,
                line=start_line,
                column=start_col,
                message=message,
                severity=2,
                syntactic_context=source,
            )

            violations.append(violation)
        return violations
Exemple #22
0
def test_run(tmp_path: Path) -> None:
    tool = SgrepTool(context_for(tmp_path, SgrepTool.tool_id(), SGREP_PATH))
    shutil.copy(SGREP_PATH / ".bento" / "sgrep.yml",
                tool.context.resource_path / "sgrep.yml")

    with _remote_docker():
        tool.setup()
        violations = set(tool.results([SGREP_PATH / "flask_configs.py"]))

    print(violations)
    expectation = {
        Violation(
            tool_id="sgrep",
            check_id="bento.avoid_hardcoded_config_DEBUG",
            path="flask_configs.py",
            line=33,
            column=1,
            message=
            "Hardcoded variable `DEBUG` detected. Set this by using FLASK_DEBUG environment variable",
            severity=2,
            syntactic_context='app.config["DEBUG"] = False',
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="sgrep",
            check_id="bento.avoid_hardcoded_config_DEBUG",
            path="flask_configs.py",
            line=31,
            column=1,
            message=
            "Hardcoded variable `DEBUG` detected. Set this by using FLASK_DEBUG environment variable",
            severity=2,
            syntactic_context='app.config["DEBUG"] = True',
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="sgrep",
            check_id="bento.avoid_hardcoded_config_ENV",
            path="flask_configs.py",
            line=27,
            column=1,
            message=
            "Hardcoded variable `ENV` detected. Set this by using FLASK_ENV environment variable",
            severity=2,
            syntactic_context='app.config["ENV"] = "production"',
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="sgrep",
            check_id="bento.avoid_hardcoded_config_ENV",
            path="flask_configs.py",
            line=25,
            column=1,
            message=
            "Hardcoded variable `ENV` detected. Set this by using FLASK_ENV environment variable",
            severity=2,
            syntactic_context='app.config["ENV"] = "development"',
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="sgrep",
            check_id="bento.avoid_hardcoded_config_SECRET_KEY",
            path="flask_configs.py",
            line=19,
            column=1,
            message=
            "Hardcoded variable `SECRET_KEY` detected. Use environment variables or config files instead",
            severity=2,
            syntactic_context='app.config.update(SECRET_KEY="aaaa")',
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="sgrep",
            check_id="bento.avoid_hardcoded_config_TESTING",
            path="flask_configs.py",
            line=15,
            column=1,
            message=
            "Hardcoded variable `TESTING` detected. Use environment variables or config files instead",
            severity=2,
            syntactic_context="app.config.update(TESTING=True)",
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="sgrep",
            check_id="bento.avoid_hardcoded_config_TESTING",
            path="flask_configs.py",
            line=13,
            column=1,
            message=
            "Hardcoded variable `TESTING` detected. Use environment variables or config files instead",
            severity=2,
            syntactic_context='app.config["TESTING"] = False',
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="sgrep",
            check_id="bento.avoid_hardcoded_config_TESTING",
            path="flask_configs.py",
            line=11,
            column=1,
            message=
            "Hardcoded variable `TESTING` detected. Use environment variables or config files instead",
            severity=2,
            syntactic_context='app.config["TESTING"] = True',
            filtered=None,
            link=None,
        ),
    }

    assert violations == expectation
Exemple #23
0
import textwrap

import bento.result as result
from bento.violation import Violation

VIOLATIONS = [
    Violation(
        tool_id="r2c.eslint",
        check_id="no-console",
        path="bento/test/integration/init.js",
        line=0,
        column=0,
        severity=1,
        message="Unexpected console statement.",
        syntactic_context="console.log(3)",
    ),
    Violation(
        tool_id="r2c.eslint",
        check_id="semi",
        path="bento/test/integration/init.js",
        line=0,
        column=0,
        message="Missing semicolon.",
        severity=2,
        syntactic_context="console.log(3)",
    ),
]

YML_TEXT = textwrap.dedent("""
    r2c_eslint:
      violations:
Exemple #24
0
def test_run(tmp_path: Path) -> None:
    tool = ShellcheckTool(
        context_for(tmp_path, ShellcheckTool.tool_id(), SHELL_INTEGRATION_PATH)
    )
    tool.setup()
    violations = set(tool.results(SHELL_TARGET))
    assert violations == {
        Violation(
            tool_id="shellcheck",
            check_id="SC2068",
            path="foo.sh",
            line=3,
            column=6,
            message="Double quote array expansions to avoid re-splitting elements.",
            severity=2,
            syntactic_context="echo $@\n",
            filtered=None,
            link="https://github.com/koalaman/shellcheck/wiki/SC2068",
        ),
        Violation(
            tool_id="shellcheck",
            check_id="SC2068",
            path="foo",
            line=3,
            column=6,
            message="Double quote array expansions to avoid re-splitting elements.",
            severity=2,
            syntactic_context="echo $@\n",
            filtered=None,
            link="https://github.com/koalaman/shellcheck/wiki/SC2068",
        ),
        Violation(
            tool_id="shellcheck",
            check_id="SC2068",
            path="bar",
            line=3,
            column=6,
            message="Double quote array expansions to avoid re-splitting elements.",
            severity=2,
            syntactic_context="echo $@\n",
            filtered=None,
            link="https://github.com/koalaman/shellcheck/wiki/SC2068",
        ),
        Violation(
            tool_id="shellcheck",
            check_id="SC2068",
            path="baz",
            line=3,
            column=6,
            message="Double quote array expansions to avoid re-splitting elements.",
            severity=2,
            syntactic_context="echo $@\n",
            filtered=None,
            link="https://github.com/koalaman/shellcheck/wiki/SC2068",
        ),
        Violation(
            tool_id="shellcheck",
            check_id="SC1083",
            path="test.sh",
            line=5,
            column=33,
            message="This { is literal. Check expression (missing ;/\\n?) or quote it.",
            severity=1,
            syntactic_context='status_code=$(curl --write-out %{http_code} --silent --output /dev/null -X POST -H "Content-Type:application/json" -d \'{\n',
            filtered=None,
            link="https://github.com/koalaman/shellcheck/wiki/SC1083",
        ),
        Violation(
            tool_id="shellcheck",
            check_id="SC1083",
            path="test.sh",
            line=5,
            column=43,
            message="This } is literal. Check expression (missing ;/\\n?) or quote it.",
            severity=1,
            syntactic_context='status_code=$(curl --write-out %{http_code} --silent --output /dev/null -X POST -H "Content-Type:application/json" -d \'{\n',
            filtered=None,
            link="https://github.com/koalaman/shellcheck/wiki/SC1083",
        ),
    }
Exemple #25
0
    SIMPLE_INTEGRATION_PATH / "foo.py",
    SIMPLE_INTEGRATION_PATH / "init.js",
    SIMPLE_INTEGRATION_PATH / "package-lock.json",
    SIMPLE_INTEGRATION_PATH / "package.json",
]
CLICK_INTEGRATION_PATH = BASE_PATH / "tests/integration/click"
CLICK_TARGETS = [CLICK_INTEGRATION_PATH / "bad_examples.py"]

EXPECTATIONS = [
    Violation(
        tool_id="r2c.click",
        check_id="option-function-argument-check",
        path="bad_examples.py",
        line=12,
        column=1,
        message=
        "function `bad_option_one` missing parameter `d` for `@click.option`",
        severity=2,
        syntactic_context="@click.command()",
        filtered=None,
        link="",
    ),
    Violation(
        tool_id="r2c.click",
        check_id="names-are-well-formed",
        path="bad_examples.py",
        line=19,
        column=1,
        message="option 'd' should begin with a '-'",
        severity=2,
        syntactic_context="@click.command()",
Exemple #26
0
def from_cache_repr(text: str) -> List[Violation]:
    parsed = json.loads(text)
    return [Violation(**kwargs) for kwargs in parsed]
Exemple #27
0
def test_run(tmp_path_factory: tmp_path_factory) -> None:
    base_path = BASE_PATH / "tests/integration/sgrep"
    tool = SGrepTool(
        context_for(tmp_path_factory, SGrepTool.tool_id(), base_path))
    tool.setup()
    violations = tool.results()
    print(violations)
    expectation = [
        Violation(
            tool_id="r2c.sgrep",
            check_id="avoid_hardcoded_config_DEBUG",
            path="flask_configs.py",
            line=33,
            column=1,
            message=
            " Hardcoded variable `DEBUG` detected. Set this by using FLASK_DEBUG environment variable",
            severity=2,
            syntactic_context='app.config["DEBUG"] = False',
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="r2c.sgrep",
            check_id="avoid_hardcoded_config_DEBUG",
            path="flask_configs.py",
            line=31,
            column=1,
            message=
            " Hardcoded variable `DEBUG` detected. Set this by using FLASK_DEBUG environment variable",
            severity=2,
            syntactic_context='app.config["DEBUG"] = True',
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="r2c.sgrep",
            check_id="avoid_hardcoded_config_ENV",
            path="flask_configs.py",
            line=27,
            column=1,
            message=
            " Hardcoded variable `ENV` detected. Set this by using FLASK_ENV environment variable",
            severity=2,
            syntactic_context='app.config["ENV"] = "production"',
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="r2c.sgrep",
            check_id="avoid_hardcoded_config_ENV",
            path="flask_configs.py",
            line=25,
            column=1,
            message=
            " Hardcoded variable `ENV` detected. Set this by using FLASK_ENV environment variable",
            severity=2,
            syntactic_context='app.config["ENV"] = "development"',
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="r2c.sgrep",
            check_id="avoid_hardcoded_config_SECRET_KEY",
            path="flask_configs.py",
            line=21,
            column=1,
            message=
            " Hardcoded variable `SECRET_KEY` detected. Use environment variables or config files instead",
            severity=2,
            syntactic_context=
            'app.config["SECRET_KEY"] = b\'_5#y2L"F4Q8z\\n\\xec]/\'',
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="r2c.sgrep",
            check_id="avoid_hardcoded_config_SECRET_KEY",
            path="flask_configs.py",
            line=19,
            column=1,
            message=
            " Hardcoded variable `SECRET_KEY` detected. Use environment variables or config files instead",
            severity=2,
            syntactic_context='app.config.update(SECRET_KEY="aaaa")',
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="r2c.sgrep",
            check_id="avoid_hardcoded_config_TESTING",
            path="flask_configs.py",
            line=15,
            column=1,
            message=
            " Hardcoded variable `TESTING` detected. Use environment variables or config files instead",
            severity=2,
            syntactic_context="app.config.update(TESTING=True)",
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="r2c.sgrep",
            check_id="avoid_hardcoded_config_TESTING",
            path="flask_configs.py",
            line=13,
            column=1,
            message=
            " Hardcoded variable `TESTING` detected. Use environment variables or config files instead",
            severity=2,
            syntactic_context='app.config["TESTING"] = False',
            filtered=None,
            link=None,
        ),
        Violation(
            tool_id="r2c.sgrep",
            check_id="avoid_hardcoded_config_TESTING",
            path="flask_configs.py",
            line=11,
            column=1,
            message=
            " Hardcoded variable `TESTING` detected. Use environment variables or config files instead",
            severity=2,
            syntactic_context='app.config["TESTING"] = True',
            filtered=None,
            link=None,
        ),
    ]

    assert violations == expectation