@codacy/tools-bandit-1 0.14.0 → 0.16.0

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/index.js CHANGED
@@ -753,7 +753,7 @@ var descriptor = {
753
753
  preferredVersion: "1.8.3",
754
754
  languages: ["Python"],
755
755
  filePatterns: ["**/*.py"],
756
- supportedOS: ["linux", "darwin"],
756
+ supportedOS: ["linux", "darwin", "win32"],
757
757
  supportedArch: ["x64", "arm64"],
758
758
  supportedRunners: ["local", "container"]
759
759
  };
@@ -786,9 +786,18 @@ function mapConfidence(confidence) {
786
786
  }
787
787
  }
788
788
  var CONFIG_FILE_CANDIDATES = [".bandit", "bandit.yml", "pyproject.toml"];
789
+ var PYPROJECT_BANDIT_SECTION = /^\[tool\.bandit(\.[\w-]+)*\]/m;
790
+ async function pyprojectHasBanditSection(pyprojectPath) {
791
+ try {
792
+ const content = await import_promises.default.readFile(pyprojectPath, "utf-8");
793
+ return PYPROJECT_BANDIT_SECTION.test(content);
794
+ } catch {
795
+ return false;
796
+ }
797
+ }
789
798
  async function resolveBinaryPath(ctx) {
790
799
  const venvDir = (0, import_tooling.getVenvDir)(ctx.globalDir, ADAPTER_ID);
791
- const venvBin = import_path.default.join(venvDir, "bin", "bandit");
800
+ const venvBin = (0, import_tooling.resolveVenvBinary)((0, import_tooling.getVenvPaths)(venvDir), "bandit");
792
801
  try {
793
802
  await import_promises.default.access(venvBin);
794
803
  return venvBin;
@@ -844,14 +853,8 @@ var adapter = {
844
853
  ];
845
854
  const venvDir = (0, import_tooling.getVenvDir)(ctx.globalDir, ADAPTER_ID);
846
855
  try {
847
- const venvPython = import_path.default.join(venvDir, "bin", "python");
848
- await import_promises.default.access(venvPython);
849
- const venv = {
850
- root: venvDir,
851
- binDir: import_path.default.join(venvDir, "bin"),
852
- python: venvPython,
853
- pip: import_path.default.join(venvDir, "bin", "pip")
854
- };
856
+ const venv = (0, import_tooling.getVenvPaths)(venvDir);
857
+ await import_promises.default.access(venv.python);
855
858
  const version = await (0, import_tooling.checkVenvTool)(
856
859
  venv,
857
860
  "bandit",
@@ -948,7 +951,9 @@ var adapter = {
948
951
  * Checks for bandit configuration files in the repository root.
949
952
  *
950
953
  * Looks for `.bandit`, `bandit.yml`, or `pyproject.toml` (in that order).
951
- * Returns the first found file.
954
+ * `pyproject.toml` only counts if it actually has a `[tool.bandit]` table —
955
+ * unlike the other two candidates, its mere existence says nothing about
956
+ * whether Bandit is configured (see {@link pyprojectHasBanditSection}).
952
957
  */
953
958
  async checkLocalConfigurationFile(ctx) {
954
959
  ctx.logger.debug("Checking for local config", { toolId: TOOL_ID });
@@ -956,6 +961,9 @@ var adapter = {
956
961
  const candidatePath = import_path.default.join(ctx.repositoryRoot, candidate);
957
962
  try {
958
963
  await import_promises.default.access(candidatePath);
964
+ if (candidate === "pyproject.toml" && !await pyprojectHasBanditSection(candidatePath)) {
965
+ continue;
966
+ }
959
967
  ctx.logger.debug("Found local config", { toolId: TOOL_ID, path: candidatePath });
960
968
  return { found: true, path: candidatePath };
961
969
  } catch {
@@ -1002,54 +1010,80 @@ var adapter = {
1002
1010
  args.push("-c", configPath);
1003
1011
  }
1004
1012
  }
1005
- args.push(...absoluteFiles);
1013
+ const fileChunks = (0, import_tooling.chunkFilesForArgv)(absoluteFiles);
1006
1014
  try {
1007
- const { stdout, stderr, exitCode } = await (0, import_tooling.spawnTool)(binary, args, {
1008
- cwd: ctx.repositoryRoot,
1009
- logger: ctx.logger
1010
- });
1011
- if (exitCode > 1) {
1012
- errors.push({
1013
- toolId: TOOL_ID,
1014
- phase: "toolInvoke",
1015
- kind: "NonZeroExit",
1016
- message: `bandit exited with code ${exitCode}${stderr ? `: ${stderr.trim()}` : ""}`,
1017
- level: "error"
1018
- });
1019
- return (0, import_tooling.buildResult)(TOOL_ID, startedAt, /* @__PURE__ */ new Date(), issues, errors, ctx.targetFiles.length);
1020
- }
1021
- if (!stdout.trim()) {
1022
- return (0, import_tooling.buildResult)(TOOL_ID, startedAt, /* @__PURE__ */ new Date(), issues, errors, ctx.targetFiles.length);
1023
- }
1024
- const jsonStart = stdout.indexOf("{");
1025
- const jsonPayload = jsonStart === -1 ? stdout : stdout.slice(jsonStart);
1026
- let banditOutput;
1027
- try {
1028
- banditOutput = JSON.parse(jsonPayload);
1029
- } catch (err) {
1030
- errors.push({
1031
- toolId: TOOL_ID,
1032
- phase: "outputParse",
1033
- kind: "MalformedOutput",
1034
- message: `Failed to parse bandit JSON output: ${err instanceof Error ? err.message : String(err)}`,
1035
- level: "error"
1015
+ const results = [];
1016
+ for (const chunk of fileChunks) {
1017
+ const { stdout, stderr, exitCode } = await (0, import_tooling.spawnTool)(binary, [...args, ...chunk], {
1018
+ cwd: ctx.repositoryRoot,
1019
+ logger: ctx.logger
1036
1020
  });
1037
- return (0, import_tooling.buildResult)(TOOL_ID, startedAt, /* @__PURE__ */ new Date(), issues, errors, ctx.targetFiles.length);
1038
- }
1039
- if (banditOutput.errors && banditOutput.errors.length > 0) {
1040
- for (const banditError of banditOutput.errors) {
1021
+ if (exitCode > 1) {
1041
1022
  errors.push({
1042
1023
  toolId: TOOL_ID,
1043
1024
  phase: "toolInvoke",
1044
- kind: "FileError",
1045
- message: `${banditError.filename}: ${banditError.reason}`,
1025
+ kind: "NonZeroExit",
1026
+ message: `bandit exited with code ${exitCode}${stderr ? `: ${stderr.trim()}` : ""}`,
1027
+ level: "error"
1028
+ });
1029
+ return (0, import_tooling.buildResult)(
1030
+ TOOL_ID,
1031
+ startedAt,
1032
+ /* @__PURE__ */ new Date(),
1033
+ issues,
1034
+ errors,
1035
+ ctx.targetFiles.length
1036
+ );
1037
+ }
1038
+ const stderrFiltered = stderr.split("\n").filter((line) => !/^\[.*\]\s+INFO\s+/.test(line.trim())).join("\n").trim();
1039
+ if (stderrFiltered) {
1040
+ errors.push({
1041
+ toolId: TOOL_ID,
1042
+ phase: "outputParse",
1043
+ kind: "ParseWarning",
1044
+ message: `bandit stderr: ${stderrFiltered}`,
1046
1045
  level: "warning"
1047
1046
  });
1048
1047
  }
1048
+ if (!stdout.trim()) continue;
1049
+ const jsonStart = stdout.indexOf("{");
1050
+ const jsonPayload = jsonStart === -1 ? stdout : stdout.slice(jsonStart);
1051
+ let banditOutput;
1052
+ try {
1053
+ banditOutput = JSON.parse(jsonPayload);
1054
+ } catch (err) {
1055
+ errors.push({
1056
+ toolId: TOOL_ID,
1057
+ phase: "outputParse",
1058
+ kind: "MalformedOutput",
1059
+ message: `Failed to parse bandit JSON output: ${err instanceof Error ? err.message : String(err)}`,
1060
+ level: "error"
1061
+ });
1062
+ return (0, import_tooling.buildResult)(
1063
+ TOOL_ID,
1064
+ startedAt,
1065
+ /* @__PURE__ */ new Date(),
1066
+ issues,
1067
+ errors,
1068
+ ctx.targetFiles.length
1069
+ );
1070
+ }
1071
+ if (banditOutput.errors && banditOutput.errors.length > 0) {
1072
+ for (const banditError of banditOutput.errors) {
1073
+ errors.push({
1074
+ toolId: TOOL_ID,
1075
+ phase: "toolInvoke",
1076
+ kind: "FileError",
1077
+ message: `${banditError.filename}: ${banditError.reason}`,
1078
+ level: "warning"
1079
+ });
1080
+ }
1081
+ }
1082
+ results.push(...banditOutput.results);
1049
1083
  }
1050
1084
  const enabledPatterns = new Set(codacyConfig.patterns.map((p) => p.patternId));
1051
1085
  const resultsByFile = /* @__PURE__ */ new Map();
1052
- for (const result2 of banditOutput.results) {
1086
+ for (const result2 of results) {
1053
1087
  const list = resultsByFile.get(result2.filename) ?? [];
1054
1088
  list.push(result2);
1055
1089
  resultsByFile.set(result2.filename, list);
@@ -1085,16 +1119,6 @@ var adapter = {
1085
1119
  issues.push(issue);
1086
1120
  }
1087
1121
  }
1088
- const stderrFiltered = stderr.split("\n").filter((line) => !/^\[.*\]\s+INFO\s+/.test(line.trim())).join("\n").trim();
1089
- if (stderrFiltered) {
1090
- errors.push({
1091
- toolId: TOOL_ID,
1092
- phase: "outputParse",
1093
- kind: "ParseWarning",
1094
- message: `bandit stderr: ${stderrFiltered}`,
1095
- level: "warning"
1096
- });
1097
- }
1098
1122
  } catch (err) {
1099
1123
  errors.push({
1100
1124
  toolId: TOOL_ID,
package/dist/metadata.js CHANGED
@@ -29,7 +29,7 @@ var descriptor = {
29
29
  preferredVersion: "1.8.3",
30
30
  languages: ["Python"],
31
31
  filePatterns: ["**/*.py"],
32
- supportedOS: ["linux", "darwin"],
32
+ supportedOS: ["linux", "darwin", "win32"],
33
33
  supportedArch: ["x64", "arm64"],
34
34
  supportedRunners: ["local", "container"]
35
35
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codacy/tools-bandit-1",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "description": "Bandit adapter — CLI-mode Python security linter",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,7 +8,7 @@
8
8
  "dist"
9
9
  ],
10
10
  "dependencies": {
11
- "@codacy/tooling": "0.14.0"
11
+ "@codacy/tooling": "0.16.0"
12
12
  },
13
13
  "license": "MIT",
14
14
  "author": "Codacy <support@codacy.com> (https://www.codacy.com)",