mobbdev 0.0.169 → 0.0.171

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.
Files changed (2) hide show
  1. package/dist/index.mjs +121 -34
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -122,6 +122,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
122
122
  IssueType_Enum2["ErroneousStringCompare"] = "ERRONEOUS_STRING_COMPARE";
123
123
  IssueType_Enum2["ErrorCondtionWithoutAction"] = "ERROR_CONDTION_WITHOUT_ACTION";
124
124
  IssueType_Enum2["GraphqlDepthLimit"] = "GRAPHQL_DEPTH_LIMIT";
125
+ IssueType_Enum2["HardcodedDomainInHtml"] = "HARDCODED_DOMAIN_IN_HTML";
125
126
  IssueType_Enum2["HardcodedSecrets"] = "HARDCODED_SECRETS";
126
127
  IssueType_Enum2["HeaderManipulation"] = "HEADER_MANIPULATION";
127
128
  IssueType_Enum2["HtmlCommentInJsp"] = "HTML_COMMENT_IN_JSP";
@@ -144,6 +145,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
144
145
  IssueType_Enum2["LogForging"] = "LOG_FORGING";
145
146
  IssueType_Enum2["MissingAntiforgeryValidation"] = "MISSING_ANTIFORGERY_VALIDATION";
146
147
  IssueType_Enum2["MissingCheckAgainstNull"] = "MISSING_CHECK_AGAINST_NULL";
148
+ IssueType_Enum2["MissingCspHeader"] = "MISSING_CSP_HEADER";
147
149
  IssueType_Enum2["MissingEqualsOrHashcode"] = "MISSING_EQUALS_OR_HASHCODE";
148
150
  IssueType_Enum2["MissingHstsHeader"] = "MISSING_HSTS_HEADER";
149
151
  IssueType_Enum2["NonFinalPublicStaticField"] = "NON_FINAL_PUBLIC_STATIC_FIELD";
@@ -188,14 +190,14 @@ var Project_Role_Type_Enum = /* @__PURE__ */ ((Project_Role_Type_Enum2) => {
188
190
  Project_Role_Type_Enum2["Writer"] = "writer";
189
191
  return Project_Role_Type_Enum2;
190
192
  })(Project_Role_Type_Enum || {});
191
- var Vulnerability_Report_Vendor_Enum = /* @__PURE__ */ ((Vulnerability_Report_Vendor_Enum3) => {
192
- Vulnerability_Report_Vendor_Enum3["Checkmarx"] = "checkmarx";
193
- Vulnerability_Report_Vendor_Enum3["CheckmarxXml"] = "checkmarxXml";
194
- Vulnerability_Report_Vendor_Enum3["Codeql"] = "codeql";
195
- Vulnerability_Report_Vendor_Enum3["Fortify"] = "fortify";
196
- Vulnerability_Report_Vendor_Enum3["Snyk"] = "snyk";
197
- Vulnerability_Report_Vendor_Enum3["Sonarqube"] = "sonarqube";
198
- return Vulnerability_Report_Vendor_Enum3;
193
+ var Vulnerability_Report_Vendor_Enum = /* @__PURE__ */ ((Vulnerability_Report_Vendor_Enum4) => {
194
+ Vulnerability_Report_Vendor_Enum4["Checkmarx"] = "checkmarx";
195
+ Vulnerability_Report_Vendor_Enum4["CheckmarxXml"] = "checkmarxXml";
196
+ Vulnerability_Report_Vendor_Enum4["Codeql"] = "codeql";
197
+ Vulnerability_Report_Vendor_Enum4["Fortify"] = "fortify";
198
+ Vulnerability_Report_Vendor_Enum4["Snyk"] = "snyk";
199
+ Vulnerability_Report_Vendor_Enum4["Sonarqube"] = "sonarqube";
200
+ return Vulnerability_Report_Vendor_Enum4;
199
201
  })(Vulnerability_Report_Vendor_Enum || {});
200
202
  var Vulnerability_Severity_Enum = /* @__PURE__ */ ((Vulnerability_Severity_Enum2) => {
201
203
  Vulnerability_Severity_Enum2["Critical"] = "critical";
@@ -308,7 +310,7 @@ var GetAnalsyisDocument = `
308
310
  var GetFixesDocument = `
309
311
  query getFixes($filters: fix_bool_exp!) {
310
312
  fixes: fix(where: $filters) {
311
- issueType
313
+ safeIssueType
312
314
  id
313
315
  vulnerabilitySeverity
314
316
  issueLanguage
@@ -738,7 +740,7 @@ var ReportQueryResultZ = z.object({
738
740
  z.object({
739
741
  id: z.string().uuid(),
740
742
  issueLanguage: z.nativeEnum(IssueLanguage_Enum).nullable(),
741
- issueType: z.nativeEnum(IssueType_Enum).nullable(),
743
+ safeIssueType: z.string(),
742
744
  confidence: z.number(),
743
745
  effortToApplyFix: z.nativeEnum(Effort_To_Apply_Fix_Enum).nullable(),
744
746
  modifiedBy: z.string().nullable(),
@@ -833,7 +835,7 @@ var ReportFixesQueryZ = z.array(
833
835
  gitBlameLogin: z.string().nullable(),
834
836
  effortToApplyFix: z.nativeEnum(Effort_To_Apply_Fix_Enum).nullable(),
835
837
  issueLanguage: z.nativeEnum(IssueLanguage_Enum).nullable(),
836
- issueType: z.nativeEnum(IssueType_Enum).nullable(),
838
+ safeIssueType: z.string(),
837
839
  vulnerabilitySeverity: z.nativeEnum(Vulnerability_Severity_Enum).nullable().transform((i) => i ?? "low" /* Low */),
838
840
  fixReportId: z.string().uuid(),
839
841
  filePaths: z.array(
@@ -903,7 +905,8 @@ var FixQueryZ = z.object({
903
905
  modifiedBy: z.string().nullable(),
904
906
  gitBlameLogin: z.string().nullable(),
905
907
  issueLanguage: z.nativeEnum(IssueLanguage_Enum).nullable(),
906
- issueType: z.nativeEnum(IssueType_Enum).nullable(),
908
+ safeIssueType: z.string(),
909
+ // issueType: z.nativeEnum(IssueType_Enum).nullable(),
907
910
  confidence: z.number(),
908
911
  fixReportId: z.string().uuid(),
909
912
  isExpired: z.boolean().default(false),
@@ -919,7 +922,6 @@ var FixQueryZ = z.object({
919
922
  vulnerabilityReportIssues: z.array(
920
923
  z.object({
921
924
  vendorIssueId: z.string(),
922
- issueType: z.string(),
923
925
  issueLanguage: z.string()
924
926
  })
925
927
  ),
@@ -990,7 +992,17 @@ var FixScreenQueryResultZ = z.object({
990
992
  }).array()
991
993
  })
992
994
  }),
993
- fix_by_pk: FixQueryZ,
995
+ fix_by_pk: FixQueryZ.merge(
996
+ z.object({
997
+ vulnerabilityReportIssues: z.array(
998
+ z.object({
999
+ vendorIssueId: z.string(),
1000
+ issueType: z.string(),
1001
+ issueLanguage: z.string()
1002
+ })
1003
+ )
1004
+ })
1005
+ ),
994
1006
  fixesWithSameIssueType: z.object({
995
1007
  fix: z.array(z.object({ id: z.string().uuid() }))
996
1008
  })
@@ -1529,7 +1541,9 @@ var fixDetailsData = {
1529
1541
  ["NO_LIMITS_OR_THROTTLING" /* NoLimitsOrThrottling */]: {
1530
1542
  issueDescription: "The lack of a rate limit can allow denial-of-service attacks, in which an attacker can cause the application to crash or become unresponsive by issuing a large number of requests simultaneously.",
1531
1543
  fixInstructions: "Use express-rate-limit npm package to set a rate limit."
1532
- }
1544
+ },
1545
+ ["MISSING_CSP_HEADER" /* MissingCspHeader */]: void 0,
1546
+ ["HARDCODED_DOMAIN_IN_HTML" /* HardcodedDomainInHtml */]: void 0
1533
1547
  };
1534
1548
 
1535
1549
  // src/features/analysis/scm/shared/src/getIssueType.ts
@@ -1605,10 +1619,12 @@ var issueTypeMap = {
1605
1619
  ["POOR_ERROR_HANDLING_EMPTY_CATCH_BLOCK" /* PoorErrorHandlingEmptyCatchBlock */]: "Poor Error Handling: Empty Catch Block",
1606
1620
  ["ERRONEOUS_STRING_COMPARE" /* ErroneousStringCompare */]: "Erroneous String Compare",
1607
1621
  ["UNVALIDATED_PUBLIC_METHOD_ARGUMENT" /* UnvalidatedPublicMethodArgument */]: "Unvalidated Public Method Argument",
1608
- ["AUTO_ESCAPE_FALSE" /* AutoEscapeFalse */]: "Auto-escape False"
1622
+ ["AUTO_ESCAPE_FALSE" /* AutoEscapeFalse */]: "Auto-escape False",
1623
+ ["MISSING_CSP_HEADER" /* MissingCspHeader */]: "Missing CSP Header",
1624
+ ["HARDCODED_DOMAIN_IN_HTML" /* HardcodedDomainInHtml */]: "Hardcoded Domain in HTML"
1609
1625
  };
1610
1626
  var issueTypeZ = z4.nativeEnum(IssueType_Enum);
1611
- var getIssueType = (issueType) => {
1627
+ var getIssueTypeFriendlyString = (issueType) => {
1612
1628
  const issueTypeZParseRes = issueTypeZ.safeParse(issueType);
1613
1629
  if (!issueTypeZParseRes.success) {
1614
1630
  return issueType ? issueType.replaceAll("_", " ") : "Other";
@@ -1643,7 +1659,7 @@ var getCommitDescription = ({
1643
1659
  if (!staticData) {
1644
1660
  return "";
1645
1661
  }
1646
- const issueTypeString = getIssueType(issueType);
1662
+ const issueTypeString = getIssueTypeFriendlyString(issueType);
1647
1663
  let description = `This change fixes a **${severity} severity** (${severityToEmoji[severity]}) **${issueTypeString}** issue reported by **${capitalizeFirstLetter(
1648
1664
  vendor
1649
1665
  )}**.
@@ -2603,6 +2619,15 @@ Make sure to pick a value large enough to allowed the nessecary amount of nested
2603
2619
  }
2604
2620
  };
2605
2621
 
2622
+ // src/features/analysis/scm/shared/src/storedQuestionData/js/hardcodedDomainInHtml.ts
2623
+ var hardcodedDomainInHtml = {
2624
+ isCDNFixedVersion: {
2625
+ content: ({ url }) => `Does the content of \`${url}\` change over time? If it does, we can't offer this fix.`,
2626
+ description: () => "You need to make sure the content of the file you are loading from the external source is persistent. To guarantee the integrity hash does not change over time, please make sure you use a proper CDN and version of the script you are loading is pinned.",
2627
+ guidance: () => ""
2628
+ }
2629
+ };
2630
+
2606
2631
  // src/features/analysis/scm/shared/src/storedQuestionData/js/hardcodedSecrets.ts
2607
2632
  var hardcodedSecrets2 = {
2608
2633
  envVarName: {
@@ -2669,6 +2694,43 @@ var logForging3 = {
2669
2694
  }
2670
2695
  };
2671
2696
 
2697
+ // src/features/analysis/scm/shared/src/storedQuestionData/js/missingCSPHeader.ts
2698
+ var cspHeaderValue = {
2699
+ cspHeaderValue: {
2700
+ content: () => "Please provide the value for the Content-Security-Policy header",
2701
+ description: () => `The Content-Security-Policy (CSP) header is a critical security measure that helps protect websites from various attacks, particularly Cross-Site Scripting (XSS) and other code injection attacks. Here's a concise explanation:
2702
+
2703
+  
2704
+  
2705
+ **What it does**:
2706
+
2707
+  
2708
+  
2709
+ CSP lets you specify which content sources the browser should consider valid, essentially creating a whitelist of trusted content. It controls things like:
2710
+
2711
+  
2712
+  
2713
+ - Which scripts can execute.
2714
+   - Where images can be loaded from.
2715
+   - Which styles can be applied.
2716
+   - Which forms can be submitted to.
2717
+   - What domains can be connected to.
2718
+  
2719
+   Default value explanation:
2720
+  
2721
+   - default-src 'self: Only allows resources from the same origin by default.
2722
+   - script-src 'self': Only allows scripts to be loaded from the same origin.
2723
+   - style-src 'self': Only allows styles from the same origin.
2724
+ &nbsp; - object-src 'none': Disallows <object>, <embed>, and <applet> elements.
2725
+ &nbsp; - base-uri 'self': Restricts where the <base> tag can point to.
2726
+ &nbsp; - frame-ancestors 'self': Ensures that only the same origin can embed the page using an iframe.
2727
+
2728
+ &nbsp;
2729
+ &nbsp; **This kind of \`CSP\` is more secure but may require adjustments for your specific application, especially if you need to load resources from external domains or use inline scripts/styles.**`,
2730
+ guidance: () => ``
2731
+ }
2732
+ };
2733
+
2672
2734
  // src/features/analysis/scm/shared/src/storedQuestionData/js/missingHSTSHeader.ts
2673
2735
  var headerMaxAge = {
2674
2736
  headerMaxAge: {
@@ -2823,7 +2885,9 @@ var vulnerabilities9 = {
2823
2885
  ["HARDCODED_SECRETS" /* HardcodedSecrets */]: hardcodedSecrets2,
2824
2886
  ["MISSING_HSTS_HEADER" /* MissingHstsHeader */]: headerMaxAge,
2825
2887
  ["UNCHECKED_LOOP_CONDITION" /* UncheckedLoopCondition */]: uncheckedLoopCondition2,
2826
- ["NO_LIMITS_OR_THROTTLING" /* NoLimitsOrThrottling */]: noLimitsOrThrottling2
2888
+ ["NO_LIMITS_OR_THROTTLING" /* NoLimitsOrThrottling */]: noLimitsOrThrottling2,
2889
+ ["MISSING_CSP_HEADER" /* MissingCspHeader */]: cspHeaderValue,
2890
+ ["HARDCODED_DOMAIN_IN_HTML" /* HardcodedDomainInHtml */]: hardcodedDomainInHtml
2827
2891
  };
2828
2892
  var js_default = vulnerabilities9;
2829
2893
 
@@ -2941,12 +3005,20 @@ function getFixGuidances({
2941
3005
  const fixGuidance = storeFixResult.success ? [storeFixResult.data.guidance({ questions, ...extraContext })] : [];
2942
3006
  return libGuidances.concat(fixGuidance).filter((guidance) => !!guidance);
2943
3007
  }
2944
- function getGuidances({
2945
- questions,
2946
- issueType,
2947
- issueLanguage,
2948
- fixExtraContext
2949
- }) {
3008
+ var IssueTypeAndLanguageZ = z8.object({
3009
+ issueType: z8.nativeEnum(IssueType_Enum),
3010
+ issueLanguage: z8.nativeEnum(IssueLanguage_Enum)
3011
+ });
3012
+ function getGuidances(args) {
3013
+ const safeIssueTypeAndLanguage = IssueTypeAndLanguageZ.safeParse({
3014
+ issueType: args.issueType,
3015
+ issueLanguage: args.issueLanguage
3016
+ });
3017
+ if (!safeIssueTypeAndLanguage.success) {
3018
+ return [];
3019
+ }
3020
+ const { questions, fixExtraContext } = args;
3021
+ const { issueType, issueLanguage } = safeIssueTypeAndLanguage.data;
2950
3022
  const fixGuidances = getFixGuidances({
2951
3023
  issueType,
2952
3024
  issueLanguage,
@@ -2957,8 +3029,8 @@ function getGuidances({
2957
3029
  let questionGuidance = question.guidance;
2958
3030
  if (!questionGuidance && issueType && issueLanguage) {
2959
3031
  const getFixInformation = curriedQuestionInformationByQuestion({
2960
- issueType: z8.nativeEnum(IssueType_Enum).parse(issueType),
2961
- language: z8.nativeEnum(IssueLanguage_Enum).parse(issueLanguage)
3032
+ issueType,
3033
+ language: issueLanguage
2962
3034
  });
2963
3035
  const { guidance } = getFixInformation(question);
2964
3036
  questionGuidance = guidance({
@@ -5819,10 +5891,12 @@ async function getAdoSdk(params) {
5819
5891
  try {
5820
5892
  const branchStatus = await git.getBranch(repo, branch, projectName);
5821
5893
  if (!branchStatus || !branchStatus.commit) {
5894
+ console.log(`no branch status: ${JSON.stringify(branchStatus)}`);
5822
5895
  throw new InvalidRepoUrlError("no branch status");
5823
5896
  }
5824
5897
  return branchStatus.name === branch;
5825
5898
  } catch (e) {
5899
+ console.error(`error in getAdoIsRemoteBranch: ${JSON.stringify(e)}`);
5826
5900
  return false;
5827
5901
  }
5828
5902
  },
@@ -6252,20 +6326,33 @@ Refresh the page in order to see the changes.`,
6252
6326
  redirectUrl: commentRes.data.html_url,
6253
6327
  commentId
6254
6328
  });
6255
- const issueType = getIssueType(fix.issueType ?? null);
6329
+ const issueType = getIssueTypeFriendlyString(fix.safeIssueType);
6256
6330
  const title = `# ${MobbIconMarkdown} ${issueType} fix is ready`;
6257
6331
  const patchAndQuestions = await PatchAndQuestionsZ.parseAsync(
6258
6332
  fix.patchAndQuestions
6259
6333
  );
6334
+ const validFixParseRes = z18.object({
6335
+ vulnerabilitySeverity: z18.nativeEnum(Vulnerability_Severity_Enum),
6336
+ issueLanguage: z18.nativeEnum(IssueLanguage_Enum),
6337
+ safeIssueType: z18.nativeEnum(IssueType_Enum)
6338
+ }).safeParse(fix);
6339
+ if (!validFixParseRes.success) {
6340
+ debug5(
6341
+ `fix ${fixId} does not have all the required fields to create a comment`,
6342
+ validFixParseRes.error
6343
+ );
6344
+ return;
6345
+ }
6346
+ const validFix = validFixParseRes.data;
6260
6347
  const subTitle = getCommitDescription({
6261
- issueType: fix.issueType,
6348
+ issueType: validFix.safeIssueType,
6262
6349
  vendor: scanner,
6263
- severity: fix.vulnerabilitySeverity,
6264
- issueLanguage: fix.issueLanguage,
6350
+ severity: validFix.vulnerabilitySeverity,
6351
+ issueLanguage: validFix.issueLanguage,
6265
6352
  guidances: getGuidances({
6266
6353
  questions: patchAndQuestions.questions.map(toQuestion),
6267
- issueType: fix.issueType,
6268
- issueLanguage: fix.issueLanguage,
6354
+ issueType: validFix.safeIssueType,
6355
+ issueLanguage: validFix.issueLanguage,
6269
6356
  fixExtraContext: patchAndQuestions.extraContext
6270
6357
  })
6271
6358
  });
@@ -6297,7 +6384,7 @@ function buildAnalysisSummaryComment(params) {
6297
6384
  if (!fix) {
6298
6385
  throw new Error(`fix ${vulnerabilityReportIssue.fixId} not found`);
6299
6386
  }
6300
- const issueType = getIssueType(fix.issueType ?? null);
6387
+ const issueType = getIssueTypeFriendlyString(fix.safeIssueType);
6301
6388
  const vulnerabilityReportIssueCount = (result[issueType] || 0) + 1;
6302
6389
  return {
6303
6390
  ...result,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobbdev",
3
- "version": "0.0.169",
3
+ "version": "0.0.171",
4
4
  "description": "Automated secure code remediation tool",
5
5
  "repository": "git+https://github.com/mobb-dev/bugsy.git",
6
6
  "main": "dist/index.js",