mobbdev 1.4.67 → 1.5.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/args/commands/upload_ai_blame.mjs +204 -130
- package/dist/index.mjs +409 -226
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -34,6 +34,18 @@ function getSdk(client, withWrapper = defaultWrapper) {
|
|
|
34
34
|
getAnalysisSubscription(variables, requestHeaders, signal) {
|
|
35
35
|
return withWrapper((wrappedRequestHeaders) => client.request({ document: GetAnalysisSubscriptionDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getAnalysisSubscription", "subscription", variables);
|
|
36
36
|
},
|
|
37
|
+
GetOrganizationId(variables, requestHeaders, signal) {
|
|
38
|
+
return withWrapper((wrappedRequestHeaders) => client.request({ document: GetOrganizationIdDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "GetOrganizationId", "query", variables);
|
|
39
|
+
},
|
|
40
|
+
UpdateOrgScanPolicy(variables, requestHeaders, signal) {
|
|
41
|
+
return withWrapper((wrappedRequestHeaders) => client.request({ document: UpdateOrgScanPolicyDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "UpdateOrgScanPolicy", "mutation", variables);
|
|
42
|
+
},
|
|
43
|
+
GetReportFindingRuleIds(variables, requestHeaders, signal) {
|
|
44
|
+
return withWrapper((wrappedRequestHeaders) => client.request({ document: GetReportFindingRuleIdsDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "GetReportFindingRuleIds", "query", variables);
|
|
45
|
+
},
|
|
46
|
+
getGateVerdict(variables, requestHeaders, signal) {
|
|
47
|
+
return withWrapper((wrappedRequestHeaders) => client.request({ document: GetGateVerdictDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getGateVerdict", "query", variables);
|
|
48
|
+
},
|
|
37
49
|
getAnalysis(variables, requestHeaders, signal) {
|
|
38
50
|
return withWrapper((wrappedRequestHeaders) => client.request({ document: GetAnalysisDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getAnalysis", "query", variables);
|
|
39
51
|
},
|
|
@@ -150,7 +162,7 @@ function getSdk(client, withWrapper = defaultWrapper) {
|
|
|
150
162
|
}
|
|
151
163
|
};
|
|
152
164
|
}
|
|
153
|
-
var AiBlameInferenceType, FixQuestionInputType, Language, ManifestAction, Effort_To_Apply_Fix_Enum, Fix_Rating_Tag_Enum, Fix_Report_State_Enum, Fix_State_Enum, IssueLanguage_Enum, Pr_Status_Enum, Project_Role_Type_Enum, Scan_Source_Enum, Vulnerability_Report_Issue_Category_Enum, Vulnerability_Report_Issue_State_Enum, Vulnerability_Report_Issue_Tag_Enum, Vulnerability_Report_Vendor_Enum, Vulnerability_Severity_Enum, FixDetailsFragmentDoc, FixReportSummaryFieldsFragmentDoc, MeDocument, GetLastOrgAndNamedProjectDocument, GetLastOrgDocument, GetEncryptedApiTokenDocument, FixReportStateDocument, GetVulnerabilityReportPathsDocument, GetAnalysisSubscriptionDocument, GetAnalysisDocument, GetFixesDocument, GetVulByNodesMetadataDocument, GetFalsePositiveDocument, UpdateScmTokenDocument, UploadS3BucketInfoDocument, GetTracyDiffUploadUrlDocument, AnalyzeCommitForExtensionAiBlameDocument, GetAiBlameInferenceDocument, GetAiBlameAttributionPromptDocument, GetPromptSummaryDocument, UploadAiBlameInferencesInitDocument, FinalizeAiBlameInferencesUploadDocument, UploadTracyRecordsDocument, GetTracyRawDataUploadUrlDocument, DigestVulnerabilityReportDocument, SubmitVulnerabilityReportDocument, CreateCommunityUserDocument, CreateCliLoginDocument, PerformCliLoginDocument, SetQuarantineEnabledDocument, CreateProjectDocument, ValidateRepoUrlDocument, GitReferenceDocument, AutoPrAnalysisDocument, GetFixWithAnswersDocument, GetFixReportsByRepoUrlDocument, GetReportFixesDocument, GetLatestReportByRepoUrlDocument, UpdateDownloadedFixDataDocument, GetUserMvsAutoFixDocument, StreamBlameAiAnalysisRequestsDocument, StreamCommitBlameRequestsDocument, ScanSkillDocument, SkillVerdictsByMd5Document, LogMvsEventDocument, GetMvsProjectDocument, IssueTypesDocument, defaultWrapper;
|
|
165
|
+
var AiBlameInferenceType, FixQuestionInputType, Language, ManifestAction, Effort_To_Apply_Fix_Enum, Fix_Rating_Tag_Enum, Fix_Report_State_Enum, Fix_State_Enum, IssueLanguage_Enum, Pr_Status_Enum, Project_Role_Type_Enum, Scan_Source_Enum, Vulnerability_Report_Issue_Category_Enum, Vulnerability_Report_Issue_State_Enum, Vulnerability_Report_Issue_Tag_Enum, Vulnerability_Report_Vendor_Enum, Vulnerability_Severity_Enum, FixDetailsFragmentDoc, FixReportSummaryFieldsFragmentDoc, MeDocument, GetLastOrgAndNamedProjectDocument, GetLastOrgDocument, GetEncryptedApiTokenDocument, FixReportStateDocument, GetVulnerabilityReportPathsDocument, GetAnalysisSubscriptionDocument, GetOrganizationIdDocument, UpdateOrgScanPolicyDocument, GetReportFindingRuleIdsDocument, GetGateVerdictDocument, GetAnalysisDocument, GetFixesDocument, GetVulByNodesMetadataDocument, GetFalsePositiveDocument, UpdateScmTokenDocument, UploadS3BucketInfoDocument, GetTracyDiffUploadUrlDocument, AnalyzeCommitForExtensionAiBlameDocument, GetAiBlameInferenceDocument, GetAiBlameAttributionPromptDocument, GetPromptSummaryDocument, UploadAiBlameInferencesInitDocument, FinalizeAiBlameInferencesUploadDocument, UploadTracyRecordsDocument, GetTracyRawDataUploadUrlDocument, DigestVulnerabilityReportDocument, SubmitVulnerabilityReportDocument, CreateCommunityUserDocument, CreateCliLoginDocument, PerformCliLoginDocument, SetQuarantineEnabledDocument, CreateProjectDocument, ValidateRepoUrlDocument, GitReferenceDocument, AutoPrAnalysisDocument, GetFixWithAnswersDocument, GetFixReportsByRepoUrlDocument, GetReportFixesDocument, GetLatestReportByRepoUrlDocument, UpdateDownloadedFixDataDocument, GetUserMvsAutoFixDocument, StreamBlameAiAnalysisRequestsDocument, StreamCommitBlameRequestsDocument, ScanSkillDocument, SkillVerdictsByMd5Document, LogMvsEventDocument, GetMvsProjectDocument, IssueTypesDocument, defaultWrapper;
|
|
154
166
|
var init_client_generates = __esm({
|
|
155
167
|
"src/features/analysis/scm/generates/client_generates.ts"() {
|
|
156
168
|
"use strict";
|
|
@@ -558,6 +570,66 @@ var init_client_generates = __esm({
|
|
|
558
570
|
state
|
|
559
571
|
failReason
|
|
560
572
|
}
|
|
573
|
+
}
|
|
574
|
+
`;
|
|
575
|
+
GetOrganizationIdDocument = `
|
|
576
|
+
query GetOrganizationId {
|
|
577
|
+
organization {
|
|
578
|
+
id
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
`;
|
|
582
|
+
UpdateOrgScanPolicyDocument = `
|
|
583
|
+
mutation UpdateOrgScanPolicy($organizationId: String!, $policyJson: String) {
|
|
584
|
+
updateOrganizationScanPolicy(
|
|
585
|
+
organizationId: $organizationId
|
|
586
|
+
policyJson: $policyJson
|
|
587
|
+
) {
|
|
588
|
+
__typename
|
|
589
|
+
... on ScanPolicyUpdateSuccess {
|
|
590
|
+
storedPolicyJson
|
|
591
|
+
warnings
|
|
592
|
+
}
|
|
593
|
+
... on ScanPolicyValidationError {
|
|
594
|
+
error
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
`;
|
|
599
|
+
GetReportFindingRuleIdsDocument = `
|
|
600
|
+
query GetReportFindingRuleIds($fixReportId: uuid!) {
|
|
601
|
+
fixReport_by_pk(id: $fixReportId) {
|
|
602
|
+
vulnerabilityReport {
|
|
603
|
+
vulnerabilityReportIssues {
|
|
604
|
+
extraData(path: "rule_id")
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
`;
|
|
610
|
+
GetGateVerdictDocument = `
|
|
611
|
+
query getGateVerdict($fixReportId: String!) {
|
|
612
|
+
getGateVerdict(fixReportId: $fixReportId) {
|
|
613
|
+
__typename
|
|
614
|
+
... on GateVerdictSuccess {
|
|
615
|
+
blocking
|
|
616
|
+
blockingCount
|
|
617
|
+
totalIssues
|
|
618
|
+
criticalCount
|
|
619
|
+
highCount
|
|
620
|
+
mediumCount
|
|
621
|
+
lowCount
|
|
622
|
+
unclassifiedCount
|
|
623
|
+
description
|
|
624
|
+
degraded
|
|
625
|
+
}
|
|
626
|
+
... on GateVerdictNotReady {
|
|
627
|
+
state
|
|
628
|
+
}
|
|
629
|
+
... on GateVerdictError {
|
|
630
|
+
error
|
|
631
|
+
}
|
|
632
|
+
}
|
|
561
633
|
}
|
|
562
634
|
`;
|
|
563
635
|
GetAnalysisDocument = `
|
|
@@ -643,35 +715,20 @@ var init_client_generates = __esm({
|
|
|
643
715
|
}
|
|
644
716
|
`;
|
|
645
717
|
GetVulByNodesMetadataDocument = `
|
|
646
|
-
query getVulByNodesMetadata($
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
where: {_or: $filters, vulnerabilityReportIssue: {fixId: {_is_null: false}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}}}
|
|
650
|
-
) {
|
|
651
|
-
vulnerabilityReportIssueId
|
|
652
|
-
path
|
|
653
|
-
startLine
|
|
654
|
-
vulnerabilityReportIssue {
|
|
655
|
-
safeIssueType
|
|
656
|
-
fixId
|
|
657
|
-
category
|
|
658
|
-
vulnerabilityReportIssueTags {
|
|
659
|
-
tag: vulnerability_report_issue_tag_value
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
fixablePrVuls: vulnerability_report_issue_aggregate(
|
|
664
|
-
where: {fixId: {_is_null: false}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}, codeNodes: {_or: $filters}}
|
|
718
|
+
query getVulByNodesMetadata($pathFilters: [vulnerability_report_issue_bool_exp!], $vulnerabilityReportId: uuid!) {
|
|
719
|
+
vulnerabilityReportIssues: vulnerability_report_issue(
|
|
720
|
+
where: {vulnerabilityReportId: {_eq: $vulnerabilityReportId}, _or: $pathFilters}
|
|
665
721
|
) {
|
|
666
|
-
|
|
667
|
-
|
|
722
|
+
id
|
|
723
|
+
safeIssueType
|
|
724
|
+
fixId
|
|
725
|
+
fpId
|
|
726
|
+
category
|
|
727
|
+
vulnerabilityReportIssueTags {
|
|
728
|
+
tag: vulnerability_report_issue_tag_value
|
|
668
729
|
}
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
where: {fixId: {_is_null: true}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}, codeNodes: {_or: $filters}}
|
|
672
|
-
) {
|
|
673
|
-
aggregate {
|
|
674
|
-
count
|
|
730
|
+
codeNodesJson {
|
|
731
|
+
nodes
|
|
675
732
|
}
|
|
676
733
|
}
|
|
677
734
|
totalScanVulnerabilities: vulnerability_report_issue_aggregate(
|
|
@@ -681,26 +738,6 @@ var init_client_generates = __esm({
|
|
|
681
738
|
count
|
|
682
739
|
}
|
|
683
740
|
}
|
|
684
|
-
irrelevantVulnerabilityReportIssue: vulnerability_report(
|
|
685
|
-
where: {id: {_eq: $vulnerabilityReportId}}
|
|
686
|
-
) {
|
|
687
|
-
vulnerabilityReportIssues(
|
|
688
|
-
where: {fixId: {_is_null: true}, category: {_in: [Irrelevant, FalsePositive, Filtered]}, _not: {vulnerabilityReportIssueTags: {vulnerability_report_issue_tag_value: {_eq: SUPPRESSED}}}}
|
|
689
|
-
) {
|
|
690
|
-
id
|
|
691
|
-
safeIssueType
|
|
692
|
-
fixId
|
|
693
|
-
category
|
|
694
|
-
vulnerabilityReportIssueTags {
|
|
695
|
-
tag: vulnerability_report_issue_tag_value
|
|
696
|
-
}
|
|
697
|
-
codeNodes(order_by: {index: desc}, where: {_or: $filters}, limit: 1) {
|
|
698
|
-
path
|
|
699
|
-
startLine
|
|
700
|
-
}
|
|
701
|
-
fpId
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
741
|
}
|
|
705
742
|
`;
|
|
706
743
|
GetFalsePositiveDocument = `
|
|
@@ -1862,7 +1899,7 @@ var init_validations = __esm({
|
|
|
1862
1899
|
|
|
1863
1900
|
// src/features/analysis/scm/shared/src/types/types.ts
|
|
1864
1901
|
import { z as z7 } from "zod";
|
|
1865
|
-
var OrganizationScreenQueryParamsZ, ProjectPageQueryParamsZ, AnalysisPageQueryParamsZ, FixPageQueryParamsZ, IssuePageQueryParamsZ, CliLoginPageQueryParamsZ, AnalysisReportDigestedZ, IssueSharedStateZ2, ReportQueryResultZ, ReportFixesQueryFixZ, BaseVulnerabilityReportIssueZ,
|
|
1902
|
+
var OrganizationScreenQueryParamsZ, ProjectPageQueryParamsZ, AnalysisPageQueryParamsZ, FixPageQueryParamsZ, IssuePageQueryParamsZ, CliLoginPageQueryParamsZ, AnalysisReportDigestedZ, IssueSharedStateZ2, ReportQueryResultZ, ReportFixesQueryFixZ, BaseVulnerabilityReportIssueZ, VulnerabilityReportIssueWithCodeFilePathZ, GetReportIssuesQueryZ, FixReportByProjectZ, FixScreenQueryResultZ, FixPageQueryZ, GetReportFixesQueryZ, GetFixReportStatsQueryZ, ProjectVulnerabilityReport, GetProjectsQueryZ, ProjectPageQueryResultZ, GetProjectMembersDataZ, RepoArgsZ, scmCloudUrl, ScmType, ConvertToSarifInputFileFormat;
|
|
1866
1903
|
var init_types = __esm({
|
|
1867
1904
|
"src/features/analysis/scm/shared/src/types/types.ts"() {
|
|
1868
1905
|
"use strict";
|
|
@@ -2124,11 +2161,6 @@ var init_types = __esm({
|
|
|
2124
2161
|
),
|
|
2125
2162
|
sharedState: VulnerabilityReportIssueSharedStateZ
|
|
2126
2163
|
});
|
|
2127
|
-
VulnerabilityReportIssueZ = BaseVulnerabilityReportIssueZ.extend(
|
|
2128
|
-
z7.object({
|
|
2129
|
-
codeNodes: z7.array(z7.object({ path: z7.string() }))
|
|
2130
|
-
}).shape
|
|
2131
|
-
);
|
|
2132
2164
|
VulnerabilityReportIssueWithCodeFilePathZ = BaseVulnerabilityReportIssueZ.extend(
|
|
2133
2165
|
z7.object({
|
|
2134
2166
|
codeFilePath: z7.string().nullable()
|
|
@@ -4263,7 +4295,7 @@ import Debug23 from "debug";
|
|
|
4263
4295
|
import { hideBin } from "yargs/helpers";
|
|
4264
4296
|
|
|
4265
4297
|
// src/args/yargs.ts
|
|
4266
|
-
import
|
|
4298
|
+
import chalk16 from "chalk";
|
|
4267
4299
|
import yargs from "yargs/yargs";
|
|
4268
4300
|
|
|
4269
4301
|
// src/args/commands/convert_to_sarif.ts
|
|
@@ -10795,6 +10827,17 @@ function createGitWithLogging(dirName, logger3 = defaultLogger) {
|
|
|
10795
10827
|
// src/utils/index.ts
|
|
10796
10828
|
var sleep = (ms = 2e3) => new Promise((r) => setTimeout(r, ms));
|
|
10797
10829
|
var CliError = class extends Error {
|
|
10830
|
+
constructor(message, options = {}) {
|
|
10831
|
+
super(message);
|
|
10832
|
+
/**
|
|
10833
|
+
* The process exit code index.ts maps this error to. Defaults to 1 (plain
|
|
10834
|
+
* operational error) so every existing throw keeps its behavior; 2 means the
|
|
10835
|
+
* gate policy blocked the run (MOBB-3810), so CI can tell "your code is
|
|
10836
|
+
* gated" from "the tool broke".
|
|
10837
|
+
*/
|
|
10838
|
+
__publicField(this, "exitCode");
|
|
10839
|
+
this.exitCode = options.exitCode ?? 1;
|
|
10840
|
+
}
|
|
10798
10841
|
};
|
|
10799
10842
|
|
|
10800
10843
|
// src/commands/fpr_stream_parser.ts
|
|
@@ -11441,6 +11484,13 @@ var scanOnlyOption = {
|
|
|
11441
11484
|
type: "boolean",
|
|
11442
11485
|
default: false
|
|
11443
11486
|
};
|
|
11487
|
+
var gateOption = {
|
|
11488
|
+
describe: chalk2.bold(
|
|
11489
|
+
"Enforce the organization's Scan & Gate Policy: after the scan, the backend decides whether any finding blocks, and the CLI exits 2 when it does (0 = pass, 1 = operational error; a scan that fails to finish exits 1, not 2). Mobb scans only \u2014 cannot be combined with --scan-file. In PR pipelines pair it with --baseline-commit so only findings new in the PR can block."
|
|
11490
|
+
),
|
|
11491
|
+
type: "boolean",
|
|
11492
|
+
default: false
|
|
11493
|
+
};
|
|
11444
11494
|
var pollingOption = {
|
|
11445
11495
|
describe: chalk2.bold(
|
|
11446
11496
|
"Use HTTP polling instead of WebSocket for status updates. Useful for proxy environments or firewalls that block WebSocket connections. Polling interval: 5 seconds, timeout: 30 minutes."
|
|
@@ -11494,10 +11544,10 @@ var ScanContext = {
|
|
|
11494
11544
|
|
|
11495
11545
|
// src/args/commands/analyze.ts
|
|
11496
11546
|
import fs13 from "fs";
|
|
11497
|
-
import
|
|
11547
|
+
import chalk11 from "chalk";
|
|
11498
11548
|
|
|
11499
11549
|
// src/commands/index.ts
|
|
11500
|
-
import
|
|
11550
|
+
import chalk9 from "chalk";
|
|
11501
11551
|
import chalkAnimation from "chalk-animation";
|
|
11502
11552
|
|
|
11503
11553
|
// src/features/analysis/index.ts
|
|
@@ -11506,7 +11556,7 @@ import fsPromises3 from "fs/promises";
|
|
|
11506
11556
|
import path11 from "path";
|
|
11507
11557
|
import { env as env2 } from "process";
|
|
11508
11558
|
import { pipeline as pipeline2 } from "stream/promises";
|
|
11509
|
-
import
|
|
11559
|
+
import chalk8 from "chalk";
|
|
11510
11560
|
import Debug22 from "debug";
|
|
11511
11561
|
import extract from "extract-zip";
|
|
11512
11562
|
import { createSpinner as createSpinner4 } from "nanospinner";
|
|
@@ -11828,65 +11878,104 @@ init_client_generates();
|
|
|
11828
11878
|
// src/features/analysis/graphql/types.ts
|
|
11829
11879
|
init_client_generates();
|
|
11830
11880
|
import { z as z22 } from "zod";
|
|
11831
|
-
|
|
11832
|
-
|
|
11881
|
+
function codeNodesJsonPathFilter(path38) {
|
|
11882
|
+
return { codeNodesJson: { nodes: { _contains: [{ path: path38 }] } } };
|
|
11883
|
+
}
|
|
11884
|
+
var VulByNodesMetadataCodeNodeZ = z22.object({
|
|
11885
|
+
index: z22.number().int(),
|
|
11833
11886
|
path: z22.string(),
|
|
11834
|
-
startLine: z22.number(),
|
|
11835
|
-
|
|
11836
|
-
|
|
11837
|
-
|
|
11838
|
-
|
|
11839
|
-
|
|
11840
|
-
|
|
11841
|
-
|
|
11842
|
-
|
|
11843
|
-
|
|
11844
|
-
})
|
|
11845
|
-
});
|
|
11846
|
-
var VulnerabilityReportIssueNoFixCodeNodeZ = z22.object({
|
|
11847
|
-
vulnerabilityReportIssues: z22.array(
|
|
11887
|
+
startLine: z22.number().int(),
|
|
11888
|
+
endLine: z22.number().int()
|
|
11889
|
+
}).loose();
|
|
11890
|
+
var VulnerabilityReportIssueWithNodesZ = z22.object({
|
|
11891
|
+
id: z22.string(),
|
|
11892
|
+
fixId: z22.string().nullable(),
|
|
11893
|
+
category: z22.enum(Vulnerability_Report_Issue_Category_Enum),
|
|
11894
|
+
safeIssueType: z22.string(),
|
|
11895
|
+
fpId: z22.guid().nullable(),
|
|
11896
|
+
vulnerabilityReportIssueTags: z22.array(
|
|
11848
11897
|
z22.object({
|
|
11849
|
-
|
|
11850
|
-
fixId: z22.string().nullable(),
|
|
11851
|
-
category: z22.enum(Vulnerability_Report_Issue_Category_Enum),
|
|
11852
|
-
safeIssueType: z22.string(),
|
|
11853
|
-
fpId: z22.guid().nullable(),
|
|
11854
|
-
codeNodes: z22.array(
|
|
11855
|
-
z22.object({
|
|
11856
|
-
path: z22.string(),
|
|
11857
|
-
startLine: z22.number()
|
|
11858
|
-
})
|
|
11859
|
-
),
|
|
11860
|
-
vulnerabilityReportIssueTags: z22.array(
|
|
11861
|
-
z22.object({
|
|
11862
|
-
tag: z22.enum(Vulnerability_Report_Issue_Tag_Enum)
|
|
11863
|
-
})
|
|
11864
|
-
)
|
|
11898
|
+
tag: z22.enum(Vulnerability_Report_Issue_Tag_Enum)
|
|
11865
11899
|
})
|
|
11866
|
-
)
|
|
11900
|
+
),
|
|
11901
|
+
codeNodesJson: z22.object({ nodes: z22.unknown() }).nullable()
|
|
11867
11902
|
});
|
|
11868
11903
|
var GetVulByNodesMetadataZ = z22.object({
|
|
11869
|
-
|
|
11870
|
-
nonFixablePrVuls: z22.object({
|
|
11871
|
-
aggregate: z22.object({
|
|
11872
|
-
count: z22.number()
|
|
11873
|
-
})
|
|
11874
|
-
}),
|
|
11875
|
-
fixablePrVuls: z22.object({
|
|
11876
|
-
aggregate: z22.object({
|
|
11877
|
-
count: z22.number()
|
|
11878
|
-
})
|
|
11879
|
-
}),
|
|
11904
|
+
vulnerabilityReportIssues: z22.array(VulnerabilityReportIssueWithNodesZ),
|
|
11880
11905
|
totalScanVulnerabilities: z22.object({
|
|
11881
11906
|
aggregate: z22.object({
|
|
11882
11907
|
count: z22.number()
|
|
11883
11908
|
})
|
|
11884
|
-
})
|
|
11885
|
-
irrelevantVulnerabilityReportIssue: z22.array(
|
|
11886
|
-
VulnerabilityReportIssueNoFixCodeNodeZ
|
|
11887
|
-
)
|
|
11909
|
+
})
|
|
11888
11910
|
});
|
|
11889
11911
|
|
|
11912
|
+
// src/features/analysis/graphql/matchVulByNodesMetadata.ts
|
|
11913
|
+
var IRRELEVANT_CATEGORIES = /* @__PURE__ */ new Set([
|
|
11914
|
+
"Irrelevant",
|
|
11915
|
+
"FalsePositive",
|
|
11916
|
+
"Filtered"
|
|
11917
|
+
]);
|
|
11918
|
+
var SUPPRESSED_TAG = "SUPPRESSED";
|
|
11919
|
+
function nodeMatchesHunks(node, hunks) {
|
|
11920
|
+
return hunks.some(
|
|
11921
|
+
(hunk) => hunk.path === node.path && hunk.ranges.some(
|
|
11922
|
+
({ startLine, endLine }) => node.startLine >= startLine && node.startLine <= endLine || node.endLine >= startLine && node.endLine <= endLine
|
|
11923
|
+
)
|
|
11924
|
+
);
|
|
11925
|
+
}
|
|
11926
|
+
function matchingNodes(issue, hunks) {
|
|
11927
|
+
const rawNodes = issue.codeNodesJson?.nodes;
|
|
11928
|
+
if (!Array.isArray(rawNodes)) {
|
|
11929
|
+
return [];
|
|
11930
|
+
}
|
|
11931
|
+
return rawNodes.map((rawNode) => VulByNodesMetadataCodeNodeZ.safeParse(rawNode)).filter((parsed) => parsed.success).map((parsed) => parsed.data).filter((node) => nodeMatchesHunks(node, hunks)).sort((a, b) => b.index - a.index);
|
|
11932
|
+
}
|
|
11933
|
+
function matchVulByNodesMetadata(issues, hunks) {
|
|
11934
|
+
const vulnerabilityReportIssueCodeNodes = [];
|
|
11935
|
+
let fixablePrVuls = 0;
|
|
11936
|
+
let nonFixablePrVuls = 0;
|
|
11937
|
+
const irrelevantVulnerabilityReportIssues = [];
|
|
11938
|
+
for (const issue of issues) {
|
|
11939
|
+
const nodes = matchingNodes(issue, hunks);
|
|
11940
|
+
const bestNode = nodes[0];
|
|
11941
|
+
if (issue.fixId !== null && bestNode) {
|
|
11942
|
+
fixablePrVuls += 1;
|
|
11943
|
+
vulnerabilityReportIssueCodeNodes.push({
|
|
11944
|
+
vulnerabilityReportIssueId: issue.id,
|
|
11945
|
+
path: bestNode.path,
|
|
11946
|
+
startLine: bestNode.startLine,
|
|
11947
|
+
vulnerabilityReportIssue: {
|
|
11948
|
+
fixId: issue.fixId,
|
|
11949
|
+
category: issue.category,
|
|
11950
|
+
safeIssueType: issue.safeIssueType,
|
|
11951
|
+
vulnerabilityReportIssueTags: issue.vulnerabilityReportIssueTags
|
|
11952
|
+
}
|
|
11953
|
+
});
|
|
11954
|
+
} else if (issue.fixId === null && bestNode) {
|
|
11955
|
+
nonFixablePrVuls += 1;
|
|
11956
|
+
}
|
|
11957
|
+
if (issue.fixId === null && IRRELEVANT_CATEGORIES.has(issue.category) && !issue.vulnerabilityReportIssueTags.some(
|
|
11958
|
+
(issueTag) => issueTag.tag === SUPPRESSED_TAG
|
|
11959
|
+
)) {
|
|
11960
|
+
irrelevantVulnerabilityReportIssues.push({
|
|
11961
|
+
id: issue.id,
|
|
11962
|
+
safeIssueType: issue.safeIssueType,
|
|
11963
|
+
fixId: issue.fixId,
|
|
11964
|
+
category: issue.category,
|
|
11965
|
+
vulnerabilityReportIssueTags: issue.vulnerabilityReportIssueTags,
|
|
11966
|
+
codeNodes: bestNode ? [{ path: bestNode.path, startLine: bestNode.startLine }] : [],
|
|
11967
|
+
fpId: issue.fpId
|
|
11968
|
+
});
|
|
11969
|
+
}
|
|
11970
|
+
}
|
|
11971
|
+
return {
|
|
11972
|
+
vulnerabilityReportIssueCodeNodes,
|
|
11973
|
+
fixablePrVuls,
|
|
11974
|
+
nonFixablePrVuls,
|
|
11975
|
+
irrelevantVulnerabilityReportIssues
|
|
11976
|
+
};
|
|
11977
|
+
}
|
|
11978
|
+
|
|
11890
11979
|
// src/features/analysis/graphql/gql.ts
|
|
11891
11980
|
var debug7 = Debug6("mobbdev:gql");
|
|
11892
11981
|
function isAuthError(error) {
|
|
@@ -12094,44 +12183,28 @@ var GQLClient = class {
|
|
|
12094
12183
|
hunks,
|
|
12095
12184
|
vulnerabilityReportId
|
|
12096
12185
|
}) {
|
|
12097
|
-
const
|
|
12098
|
-
const filter = {
|
|
12099
|
-
path: { _eq: hunk.path },
|
|
12100
|
-
_or: hunk.ranges.flatMap(({ endLine, startLine }) => {
|
|
12101
|
-
return [
|
|
12102
|
-
{ startLine: { _gte: startLine, _lte: endLine } },
|
|
12103
|
-
{ endLine: { _gte: startLine, _lte: endLine } }
|
|
12104
|
-
];
|
|
12105
|
-
})
|
|
12106
|
-
};
|
|
12107
|
-
return filter;
|
|
12108
|
-
});
|
|
12186
|
+
const pathFilters = hunks.map((hunk) => codeNodesJsonPathFilter(hunk.path));
|
|
12109
12187
|
const getVulByNodesMetadataRes = await this._clientSdk.getVulByNodesMetadata({
|
|
12110
|
-
|
|
12188
|
+
pathFilters,
|
|
12111
12189
|
vulnerabilityReportId
|
|
12112
12190
|
});
|
|
12113
12191
|
const parsedGetVulByNodesMetadataRes = GetVulByNodesMetadataZ.parse(
|
|
12114
12192
|
getVulByNodesMetadataRes
|
|
12115
12193
|
);
|
|
12116
|
-
const
|
|
12117
|
-
|
|
12118
|
-
|
|
12119
|
-
|
|
12120
|
-
|
|
12121
|
-
|
|
12122
|
-
|
|
12123
|
-
|
|
12124
|
-
|
|
12125
|
-
const nonFixablePrVuls = parsedGetVulByNodesMetadataRes.nonFixablePrVuls.aggregate.count;
|
|
12126
|
-
const fixablePrVuls = parsedGetVulByNodesMetadataRes.fixablePrVuls.aggregate.count;
|
|
12194
|
+
const {
|
|
12195
|
+
vulnerabilityReportIssueCodeNodes,
|
|
12196
|
+
fixablePrVuls,
|
|
12197
|
+
nonFixablePrVuls,
|
|
12198
|
+
irrelevantVulnerabilityReportIssues
|
|
12199
|
+
} = matchVulByNodesMetadata(
|
|
12200
|
+
parsedGetVulByNodesMetadataRes.vulnerabilityReportIssues,
|
|
12201
|
+
hunks
|
|
12202
|
+
);
|
|
12127
12203
|
const totalScanVulnerabilities = parsedGetVulByNodesMetadataRes.totalScanVulnerabilities.aggregate.count;
|
|
12128
12204
|
const vulnerabilitiesOutsidePr = totalScanVulnerabilities - nonFixablePrVuls - fixablePrVuls;
|
|
12129
12205
|
const totalPrVulnerabilities = nonFixablePrVuls + fixablePrVuls;
|
|
12130
|
-
const irrelevantVulnerabilityReportIssues = parsedGetVulByNodesMetadataRes.irrelevantVulnerabilityReportIssue?.[0]?.vulnerabilityReportIssues ?? [];
|
|
12131
12206
|
return {
|
|
12132
|
-
vulnerabilityReportIssueCodeNodes
|
|
12133
|
-
uniqueVulByNodesMetadata
|
|
12134
|
-
),
|
|
12207
|
+
vulnerabilityReportIssueCodeNodes,
|
|
12135
12208
|
nonFixablePrVuls,
|
|
12136
12209
|
fixablePrVuls,
|
|
12137
12210
|
totalScanVulnerabilities,
|
|
@@ -12339,6 +12412,14 @@ var GQLClient = class {
|
|
|
12339
12412
|
}
|
|
12340
12413
|
return res.analysis;
|
|
12341
12414
|
}
|
|
12415
|
+
/**
|
|
12416
|
+
* The gate verdict for a Mobb-scan report (MOBB-3810). The backend is the
|
|
12417
|
+
* only decider; the caller maps the answer onto an exit code.
|
|
12418
|
+
*/
|
|
12419
|
+
async getGateVerdict(fixReportId) {
|
|
12420
|
+
const res = await this._clientSdk.getGateVerdict({ fixReportId });
|
|
12421
|
+
return res.getGateVerdict;
|
|
12422
|
+
}
|
|
12342
12423
|
async autoPrAnalysis({
|
|
12343
12424
|
analysisId,
|
|
12344
12425
|
commitDirectly,
|
|
@@ -14571,6 +14652,36 @@ async function handleAutoPr(params) {
|
|
|
14571
14652
|
}
|
|
14572
14653
|
}
|
|
14573
14654
|
|
|
14655
|
+
// src/features/analysis/gate_verdict.ts
|
|
14656
|
+
import chalk5 from "chalk";
|
|
14657
|
+
async function enforceGateVerdict({
|
|
14658
|
+
gqlClient,
|
|
14659
|
+
fixReportId
|
|
14660
|
+
}) {
|
|
14661
|
+
const verdict = await gqlClient.getGateVerdict(fixReportId);
|
|
14662
|
+
if (verdict.__typename === "GateVerdictError") {
|
|
14663
|
+
throw new CliError(`\u{1F6A7} Gate verdict unavailable: ${verdict.error}`);
|
|
14664
|
+
}
|
|
14665
|
+
if (verdict.__typename === "GateVerdictNotReady") {
|
|
14666
|
+
throw new CliError(
|
|
14667
|
+
`\u{1F6A7} Gate verdict not ready \u2014 report state is ${verdict.state}`
|
|
14668
|
+
);
|
|
14669
|
+
}
|
|
14670
|
+
if (verdict.degraded) {
|
|
14671
|
+
console.log(
|
|
14672
|
+
chalk5.yellow(
|
|
14673
|
+
"\u26A0\uFE0F The gate policy could not be read; the fail-closed default was applied."
|
|
14674
|
+
)
|
|
14675
|
+
);
|
|
14676
|
+
}
|
|
14677
|
+
if (verdict.blocking) {
|
|
14678
|
+
throw new CliError(chalk5.red(`\u{1F6A7} Gate: ${verdict.description}`), {
|
|
14679
|
+
exitCode: 2
|
|
14680
|
+
});
|
|
14681
|
+
}
|
|
14682
|
+
console.log(chalk5.green(`\u{1F6A7} Gate: ${verdict.description}`));
|
|
14683
|
+
}
|
|
14684
|
+
|
|
14574
14685
|
// src/features/analysis/git.ts
|
|
14575
14686
|
init_GitService();
|
|
14576
14687
|
import Debug17 from "debug";
|
|
@@ -14799,7 +14910,7 @@ async function snykArticlePrompt() {
|
|
|
14799
14910
|
|
|
14800
14911
|
// src/features/analysis/scanners/checkmarx.ts
|
|
14801
14912
|
import { createRequire } from "module";
|
|
14802
|
-
import
|
|
14913
|
+
import chalk6 from "chalk";
|
|
14803
14914
|
import Debug20 from "debug";
|
|
14804
14915
|
import { existsSync } from "fs";
|
|
14805
14916
|
import { createSpinner as createSpinner2 } from "nanospinner";
|
|
@@ -14970,7 +15081,7 @@ async function throwCheckmarxConfigError() {
|
|
|
14970
15081
|
await createSpinner2("\u{1F513} Checkmarx is not configued correctly").start().error();
|
|
14971
15082
|
throw new CliError(
|
|
14972
15083
|
`Checkmarx is not configued correctly
|
|
14973
|
-
you can configure it by using the ${
|
|
15084
|
+
you can configure it by using the ${chalk6.bold(
|
|
14974
15085
|
"cx configure"
|
|
14975
15086
|
)} command`
|
|
14976
15087
|
);
|
|
@@ -14978,8 +15089,8 @@ async function throwCheckmarxConfigError() {
|
|
|
14978
15089
|
async function validateCheckamxCredentials() {
|
|
14979
15090
|
console.log(`
|
|
14980
15091
|
Here's a suggestion for checkmarx configuation:
|
|
14981
|
-
${
|
|
14982
|
-
${
|
|
15092
|
+
${chalk6.bold("AST Base URI:")} https://ast.checkmarx.net
|
|
15093
|
+
${chalk6.bold("AST Base Auth URI (IAM):")} https://iam.checkmarx.net
|
|
14983
15094
|
`);
|
|
14984
15095
|
await forkCheckmarx(CONFIGURE_COMMAND, { display: true });
|
|
14985
15096
|
const { code: loginCode } = await forkCheckmarx(VALIDATE_COMMAND, {
|
|
@@ -15004,7 +15115,7 @@ import os4 from "os";
|
|
|
15004
15115
|
import path10 from "path";
|
|
15005
15116
|
import { Readable } from "stream";
|
|
15006
15117
|
import { pipeline } from "stream/promises";
|
|
15007
|
-
import
|
|
15118
|
+
import chalk7 from "chalk";
|
|
15008
15119
|
import Debug21 from "debug";
|
|
15009
15120
|
import { createSpinner as createSpinner3 } from "nanospinner";
|
|
15010
15121
|
import open2 from "open";
|
|
@@ -15168,7 +15279,7 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
|
|
|
15168
15279
|
await open2(SNYK_ARTICLE_URL);
|
|
15169
15280
|
}
|
|
15170
15281
|
console.log(
|
|
15171
|
-
|
|
15282
|
+
chalk7.bgBlue(
|
|
15172
15283
|
"\nPlease enable Snyk Code in your Snyk account and try again."
|
|
15173
15284
|
)
|
|
15174
15285
|
);
|
|
@@ -15224,7 +15335,7 @@ async function downloadRepo({
|
|
|
15224
15335
|
if (!response.ok) {
|
|
15225
15336
|
debug22("SCM zipball request failed %s %s", response.body, response.status);
|
|
15226
15337
|
repoSpinner.error({ text: "\u{1F4BE} Repo download failed" });
|
|
15227
|
-
throw new Error(`Can't access ${
|
|
15338
|
+
throw new Error(`Can't access ${chalk8.bold(repoUrl)}`);
|
|
15228
15339
|
}
|
|
15229
15340
|
const fileWriterStream = fs11.createWriteStream(zipFilePath);
|
|
15230
15341
|
if (!response.body) {
|
|
@@ -15391,7 +15502,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
15391
15502
|
pullRequest,
|
|
15392
15503
|
polling,
|
|
15393
15504
|
baselineCommit,
|
|
15394
|
-
scanOnly: requestedScanOnly
|
|
15505
|
+
scanOnly: requestedScanOnly,
|
|
15506
|
+
gate
|
|
15395
15507
|
} = params;
|
|
15396
15508
|
debug22("start %s %s", dirname, repo);
|
|
15397
15509
|
const { createSpinner: createSpinner5 } = Spinner2({ ci });
|
|
@@ -15401,6 +15513,15 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
15401
15513
|
isSkipPrompts: skipPrompts
|
|
15402
15514
|
});
|
|
15403
15515
|
await gqlClient.loadIssueTypeCatalog();
|
|
15516
|
+
const runGate = async (fixReportId) => {
|
|
15517
|
+
await waitForAnalysisFinished({
|
|
15518
|
+
gqlClient,
|
|
15519
|
+
analysisId: fixReportId,
|
|
15520
|
+
polling,
|
|
15521
|
+
ci
|
|
15522
|
+
});
|
|
15523
|
+
await enforceGateVerdict({ gqlClient, fixReportId });
|
|
15524
|
+
};
|
|
15404
15525
|
if (!mobbProjectName) {
|
|
15405
15526
|
throw new Error("mobbProjectName is required");
|
|
15406
15527
|
}
|
|
@@ -15416,7 +15537,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
15416
15537
|
const scanOnly = requestedScanOnly || !orgIsFixEnabled;
|
|
15417
15538
|
if (scanOnly && !requestedScanOnly) {
|
|
15418
15539
|
console.log(
|
|
15419
|
-
|
|
15540
|
+
chalk8.yellow(
|
|
15420
15541
|
"\u2139\uFE0F Your organization is on Mobb Scan (scan-only): issues will be found and reported, but no fixes are generated. Contact support to enable Mobb Fixer."
|
|
15421
15542
|
)
|
|
15422
15543
|
);
|
|
@@ -15571,6 +15692,9 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
15571
15692
|
polling
|
|
15572
15693
|
});
|
|
15573
15694
|
}
|
|
15695
|
+
if (gate) {
|
|
15696
|
+
await runGate(reportUploadInfo.fixReportId);
|
|
15697
|
+
}
|
|
15574
15698
|
return reportUploadInfo.fixReportId;
|
|
15575
15699
|
async function askToOpenAnalysis() {
|
|
15576
15700
|
if (!repoUploadInfo || !reportUploadInfo) {
|
|
@@ -15582,11 +15706,11 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
15582
15706
|
fixReportId: reportUploadInfo.fixReportId
|
|
15583
15707
|
});
|
|
15584
15708
|
!ci && console.log("You can access the analysis at: \n");
|
|
15585
|
-
console.log(
|
|
15709
|
+
console.log(chalk8.bold(reportUrl));
|
|
15586
15710
|
!skipPrompts && await mobbAnalysisPrompt();
|
|
15587
15711
|
!ci && open3(reportUrl);
|
|
15588
15712
|
!ci && console.log(
|
|
15589
|
-
|
|
15713
|
+
chalk8.bgBlue("\n\n My work here is done for now, see you soon! \u{1F575}\uFE0F\u200D\u2642\uFE0F ")
|
|
15590
15714
|
);
|
|
15591
15715
|
}
|
|
15592
15716
|
async function handleScmIntegration(oldToken, scmAuthUrl2, repoUrl) {
|
|
@@ -15745,6 +15869,9 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
15745
15869
|
});
|
|
15746
15870
|
}
|
|
15747
15871
|
await askToOpenAnalysis();
|
|
15872
|
+
if (gate) {
|
|
15873
|
+
await runGate(reportUploadInfo.fixReportId);
|
|
15874
|
+
}
|
|
15748
15875
|
return reportUploadInfo.fixReportId;
|
|
15749
15876
|
}
|
|
15750
15877
|
}
|
|
@@ -15823,7 +15950,7 @@ async function _digestReport({
|
|
|
15823
15950
|
"[_digestReport] Using POLLING mode for analysis state updates (--polling flag enabled)"
|
|
15824
15951
|
);
|
|
15825
15952
|
console.log(
|
|
15826
|
-
|
|
15953
|
+
chalk8.cyan(
|
|
15827
15954
|
"\u{1F504} [Polling Mode] Using HTTP polling instead of WebSocket for status updates"
|
|
15828
15955
|
)
|
|
15829
15956
|
);
|
|
@@ -15838,7 +15965,7 @@ async function _digestReport({
|
|
|
15838
15965
|
"[_digestReport] Using WEBSOCKET mode for analysis state updates (default)"
|
|
15839
15966
|
);
|
|
15840
15967
|
console.log(
|
|
15841
|
-
|
|
15968
|
+
chalk8.cyan(
|
|
15842
15969
|
"\u{1F50C} [WebSocket Mode] Using WebSocket subscription for status updates"
|
|
15843
15970
|
)
|
|
15844
15971
|
);
|
|
@@ -15902,7 +16029,7 @@ async function waitForAnaysisAndReviewPr({
|
|
|
15902
16029
|
"[waitForAnaysisAndReviewPr] Using POLLING mode for analysis state updates"
|
|
15903
16030
|
);
|
|
15904
16031
|
console.log(
|
|
15905
|
-
|
|
16032
|
+
chalk8.cyan(
|
|
15906
16033
|
"\u{1F504} [Polling Mode] Waiting for analysis completion using HTTP polling"
|
|
15907
16034
|
)
|
|
15908
16035
|
);
|
|
@@ -15916,7 +16043,7 @@ async function waitForAnaysisAndReviewPr({
|
|
|
15916
16043
|
"[waitForAnaysisAndReviewPr] Using WEBSOCKET mode for analysis state updates"
|
|
15917
16044
|
);
|
|
15918
16045
|
console.log(
|
|
15919
|
-
|
|
16046
|
+
chalk8.cyan(
|
|
15920
16047
|
"\u{1F50C} [WebSocket Mode] Waiting for analysis completion using WebSocket"
|
|
15921
16048
|
)
|
|
15922
16049
|
);
|
|
@@ -15929,6 +16056,41 @@ async function waitForAnaysisAndReviewPr({
|
|
|
15929
16056
|
});
|
|
15930
16057
|
}
|
|
15931
16058
|
}
|
|
16059
|
+
async function waitForAnalysisFinished({
|
|
16060
|
+
gqlClient,
|
|
16061
|
+
analysisId,
|
|
16062
|
+
polling,
|
|
16063
|
+
ci
|
|
16064
|
+
}) {
|
|
16065
|
+
const { createSpinner: createSpinner5 } = Spinner2({ ci });
|
|
16066
|
+
const gateSpinner = createSpinner5(
|
|
16067
|
+
"\u{1F6A7} Waiting for the analysis to finish to evaluate the gate\u2026"
|
|
16068
|
+
).start();
|
|
16069
|
+
const callback = () => void 0;
|
|
16070
|
+
try {
|
|
16071
|
+
if (polling) {
|
|
16072
|
+
await gqlClient.pollForAnalysisState({
|
|
16073
|
+
analysisId,
|
|
16074
|
+
callback,
|
|
16075
|
+
callbackStates: ["Finished" /* Finished */]
|
|
16076
|
+
});
|
|
16077
|
+
} else {
|
|
16078
|
+
await gqlClient.subscribeToAnalysis({
|
|
16079
|
+
subscribeToAnalysisParams: {
|
|
16080
|
+
analysisId
|
|
16081
|
+
},
|
|
16082
|
+
callback,
|
|
16083
|
+
callbackStates: ["Finished" /* Finished */]
|
|
16084
|
+
});
|
|
16085
|
+
}
|
|
16086
|
+
} catch (e) {
|
|
16087
|
+
gateSpinner.error({
|
|
16088
|
+
text: e instanceof ReportDigestError ? "\u{1F6A7} Analysis failed \u2014 cannot evaluate the gate" : "\u{1F6A7} Analysis did not finish"
|
|
16089
|
+
});
|
|
16090
|
+
throw e;
|
|
16091
|
+
}
|
|
16092
|
+
gateSpinner.success({ text: "\u{1F6A7} Analysis finished, evaluating the gate" });
|
|
16093
|
+
}
|
|
15932
16094
|
|
|
15933
16095
|
// src/commands/scan_skill_input.ts
|
|
15934
16096
|
import fs12 from "fs";
|
|
@@ -16060,7 +16222,8 @@ async function analyze({
|
|
|
16060
16222
|
pullRequest,
|
|
16061
16223
|
polling,
|
|
16062
16224
|
baselineCommit,
|
|
16063
|
-
scanOnly
|
|
16225
|
+
scanOnly,
|
|
16226
|
+
gate
|
|
16064
16227
|
}, { skipPrompts = false } = {}) {
|
|
16065
16228
|
!ci && await showWelcomeMessage(skipPrompts);
|
|
16066
16229
|
await runAnalysis(
|
|
@@ -16081,7 +16244,8 @@ async function analyze({
|
|
|
16081
16244
|
createOnePr,
|
|
16082
16245
|
polling,
|
|
16083
16246
|
baselineCommit,
|
|
16084
|
-
scanOnly
|
|
16247
|
+
scanOnly,
|
|
16248
|
+
gate
|
|
16085
16249
|
},
|
|
16086
16250
|
{ skipPrompts }
|
|
16087
16251
|
);
|
|
@@ -16156,14 +16320,14 @@ async function scanSkill(options) {
|
|
|
16156
16320
|
inputApiKey: apiKey,
|
|
16157
16321
|
isSkipPrompts: ci
|
|
16158
16322
|
});
|
|
16159
|
-
console.log(
|
|
16323
|
+
console.log(chalk9.dim(`Scanning skill: ${url}`));
|
|
16160
16324
|
console.log();
|
|
16161
16325
|
const skillUrl = await resolveSkillScanInput(url);
|
|
16162
16326
|
const result = await gqlClient.scanSkill({ skillUrl });
|
|
16163
16327
|
const scan2 = result.scanSkill;
|
|
16164
16328
|
const verdictColor = VERDICT_COLORS[scan2.verdict] ?? "white";
|
|
16165
16329
|
console.log(
|
|
16166
|
-
|
|
16330
|
+
chalk9.bold(`Verdict: `) + chalk9[verdictColor](
|
|
16167
16331
|
scan2.verdict
|
|
16168
16332
|
)
|
|
16169
16333
|
);
|
|
@@ -16175,32 +16339,32 @@ async function scanSkill(options) {
|
|
|
16175
16339
|
console.log(`Findings: ${scan2.findingsCount}`);
|
|
16176
16340
|
console.log(`Duration: ${scan2.scanDurationMs}ms`);
|
|
16177
16341
|
if (scan2.cached) {
|
|
16178
|
-
console.log(
|
|
16342
|
+
console.log(chalk9.dim("(cached result)"));
|
|
16179
16343
|
}
|
|
16180
16344
|
console.log();
|
|
16181
16345
|
if (scan2.findings.length > 0) {
|
|
16182
|
-
console.log(
|
|
16346
|
+
console.log(chalk9.bold("Findings:"));
|
|
16183
16347
|
console.log();
|
|
16184
16348
|
for (const f of scan2.findings) {
|
|
16185
16349
|
const sevColor = SEVERITY_COLORS[f.severity] ?? "white";
|
|
16186
16350
|
const location = [f.filePath, f.lineNumber].filter(Boolean).join(":");
|
|
16187
16351
|
console.log(
|
|
16188
|
-
` ${
|
|
16352
|
+
` ${chalk9[sevColor](f.severity)} [${f.layer}] ${f.category}${f.ruleId ? ` (${f.ruleId})` : ""}`
|
|
16189
16353
|
);
|
|
16190
16354
|
if (location) {
|
|
16191
|
-
console.log(` ${
|
|
16355
|
+
console.log(` ${chalk9.dim(location)}`);
|
|
16192
16356
|
}
|
|
16193
16357
|
console.log(` ${f.explanation}`);
|
|
16194
16358
|
if (f.evidence) {
|
|
16195
16359
|
console.log(
|
|
16196
|
-
` ${String(
|
|
16360
|
+
` ${String(chalk9.dim("Evidence: " + f.evidence.slice(0, 120))).replace(/\n|\r/g, "")}`
|
|
16197
16361
|
);
|
|
16198
16362
|
}
|
|
16199
16363
|
console.log();
|
|
16200
16364
|
}
|
|
16201
16365
|
}
|
|
16202
16366
|
if (scan2.summary) {
|
|
16203
|
-
console.log(
|
|
16367
|
+
console.log(chalk9.bold("Analysis:"));
|
|
16204
16368
|
console.log(` ${scan2.summary}`);
|
|
16205
16369
|
console.log();
|
|
16206
16370
|
}
|
|
@@ -16210,7 +16374,7 @@ async function scanSkill(options) {
|
|
|
16210
16374
|
}
|
|
16211
16375
|
|
|
16212
16376
|
// src/args/validation.ts
|
|
16213
|
-
import
|
|
16377
|
+
import chalk10 from "chalk";
|
|
16214
16378
|
import path13 from "path";
|
|
16215
16379
|
import { z as z28 } from "zod";
|
|
16216
16380
|
function throwRepoUrlErrorMessage({
|
|
@@ -16220,11 +16384,11 @@ function throwRepoUrlErrorMessage({
|
|
|
16220
16384
|
}) {
|
|
16221
16385
|
const errorMessage3 = error.issues[error.issues.length - 1]?.message;
|
|
16222
16386
|
const formattedErrorMessage = `
|
|
16223
|
-
Error: ${
|
|
16387
|
+
Error: ${chalk10.bold(
|
|
16224
16388
|
repoUrl
|
|
16225
16389
|
)} is ${errorMessage3}
|
|
16226
16390
|
Example:
|
|
16227
|
-
mobbdev ${command} -r ${
|
|
16391
|
+
mobbdev ${command} -r ${chalk10.bold(
|
|
16228
16392
|
"https://github.com/WebGoat/WebGoat"
|
|
16229
16393
|
)}`;
|
|
16230
16394
|
throw new CliError(formattedErrorMessage);
|
|
@@ -16258,9 +16422,9 @@ function validateReportFileFormat(reportFile) {
|
|
|
16258
16422
|
if (!supportExtensions.includes(path13.extname(reportFile))) {
|
|
16259
16423
|
throw new CliError(
|
|
16260
16424
|
`
|
|
16261
|
-
${
|
|
16425
|
+
${chalk10.bold(
|
|
16262
16426
|
reportFile
|
|
16263
|
-
)} is not a supported file extension. Supported extensions are: ${
|
|
16427
|
+
)} is not a supported file extension. Supported extensions are: ${chalk10.bold(
|
|
16264
16428
|
supportExtensions.join(", ")
|
|
16265
16429
|
)}
|
|
16266
16430
|
`
|
|
@@ -16273,27 +16437,30 @@ function analyzeBuilder(yargs2) {
|
|
|
16273
16437
|
return yargs2.option("f", {
|
|
16274
16438
|
alias: "scan-file",
|
|
16275
16439
|
type: "string",
|
|
16276
|
-
describe:
|
|
16440
|
+
describe: chalk11.bold(
|
|
16277
16441
|
"Select the vulnerability report to analyze (Checkmarx, Snyk, Fortify, CodeQL, Sonarqube, Semgrep, Datadog, Black Duck)"
|
|
16278
16442
|
)
|
|
16279
16443
|
}).option("repo", repoOption).option("p", {
|
|
16280
16444
|
alias: "src-path",
|
|
16281
|
-
describe:
|
|
16445
|
+
describe: chalk11.bold(
|
|
16282
16446
|
"Path to the repository folder with the source code; alternatively, you can specify the Fortify FPR file to extract source code out of it"
|
|
16283
16447
|
),
|
|
16284
16448
|
type: "string"
|
|
16285
16449
|
}).option("ref", refOption).option("ch", {
|
|
16286
16450
|
alias: "commit-hash",
|
|
16287
|
-
describe:
|
|
16451
|
+
describe: chalk11.bold("Hash of the commit"),
|
|
16288
16452
|
type: "string"
|
|
16289
16453
|
}).option("mobb-project-name", mobbProjectNameOption).option("y", yesOption).option("ci", ciOption).option("org", organizationIdOptions).option("api-key", apiKeyOption).option("commit-hash", commitHashOption).option("auto-pr", autoPrOption).option("create-one-pr", createOnePrOption).option("commit-directly", commitDirectlyOption).option("pull-request", {
|
|
16290
16454
|
alias: ["pr", "pr-number", "pr-id"],
|
|
16291
|
-
describe:
|
|
16455
|
+
describe: chalk11.bold("Number of the pull request"),
|
|
16292
16456
|
type: "number",
|
|
16293
16457
|
demandOption: false
|
|
16294
|
-
}).option("polling", pollingOption).option("baseline-commit", baselineCommitOption).option("scan-only", scanOnlyOption).example(
|
|
16458
|
+
}).option("polling", pollingOption).option("baseline-commit", baselineCommitOption).option("scan-only", scanOnlyOption).option("gate", gateOption).example(
|
|
16295
16459
|
"npx mobbdev@latest analyze -r https://github.com/org/repo --scan-only",
|
|
16296
16460
|
"scan only \u2014 report findings without generating fixes"
|
|
16461
|
+
).example(
|
|
16462
|
+
"npx mobbdev@latest analyze -r https://github.com/org/repo --ci --api-key <key> --baseline-commit <sha> --gate",
|
|
16463
|
+
"PR pipeline: scan the diff and fail the build (exit 2) when the Scan & Gate Policy blocks"
|
|
16297
16464
|
).example(
|
|
16298
16465
|
"npx mobbdev@latest analyze -r https://github.com/WebGoat/WebGoat -f <your_vulnerability_report_path>",
|
|
16299
16466
|
"analyze an existing repository"
|
|
@@ -16303,9 +16470,14 @@ function analyzeBuilder(yargs2) {
|
|
|
16303
16470
|
).help();
|
|
16304
16471
|
}
|
|
16305
16472
|
function validateAnalyzeOptions(argv) {
|
|
16473
|
+
if (argv.gate && argv.f) {
|
|
16474
|
+
throw new CliError(
|
|
16475
|
+
"--gate enforces the policy on a Mobb scan and cannot be combined with --scan-file"
|
|
16476
|
+
);
|
|
16477
|
+
}
|
|
16306
16478
|
if (argv.f && !fs13.existsSync(argv.f)) {
|
|
16307
16479
|
throw new CliError(`
|
|
16308
|
-
Can't access ${
|
|
16480
|
+
Can't access ${chalk11.bold(argv.f)}`);
|
|
16309
16481
|
}
|
|
16310
16482
|
validateOrganizationId(argv.organizationId);
|
|
16311
16483
|
if (!argv.srcPath && !argv.repo) {
|
|
@@ -16343,7 +16515,15 @@ Can't access ${chalk10.bold(argv.f)}`);
|
|
|
16343
16515
|
}
|
|
16344
16516
|
async function analyzeHandler(args) {
|
|
16345
16517
|
validateAnalyzeOptions(args);
|
|
16346
|
-
|
|
16518
|
+
try {
|
|
16519
|
+
await analyze(args, { skipPrompts: args.yes });
|
|
16520
|
+
} catch (err) {
|
|
16521
|
+
if (err instanceof CliError && err.exitCode !== 1) {
|
|
16522
|
+
console.error(err.message);
|
|
16523
|
+
process.exit(err.exitCode);
|
|
16524
|
+
}
|
|
16525
|
+
throw err;
|
|
16526
|
+
}
|
|
16347
16527
|
}
|
|
16348
16528
|
|
|
16349
16529
|
// src/args/commands/claude_code.ts
|
|
@@ -18614,7 +18794,7 @@ function createLogger(config2) {
|
|
|
18614
18794
|
|
|
18615
18795
|
// src/features/claude_code/hook_logger.ts
|
|
18616
18796
|
var DD_RUM_TOKEN = true ? "pubf59c0182545bfb4c299175119f1abf9b" : "";
|
|
18617
|
-
var CLI_VERSION = true ? "1.
|
|
18797
|
+
var CLI_VERSION = true ? "1.5.0" : "unknown";
|
|
18618
18798
|
var NAMESPACE = "mobbdev-claude-code-hook-logs";
|
|
18619
18799
|
var claudeCodeVersion;
|
|
18620
18800
|
function buildDdTags() {
|
|
@@ -19281,7 +19461,7 @@ import fs15 from "fs";
|
|
|
19281
19461
|
import fsPromises4 from "fs/promises";
|
|
19282
19462
|
import os7 from "os";
|
|
19283
19463
|
import path23 from "path";
|
|
19284
|
-
import
|
|
19464
|
+
import chalk12 from "chalk";
|
|
19285
19465
|
|
|
19286
19466
|
// src/features/claude_code/daemon-check-shim.tmpl.js
|
|
19287
19467
|
var daemon_check_shim_tmpl_default = "// Mobb daemon shim \u2014 checks if daemon is alive, spawns if dead.\n// Auto-generated by mobbdev CLI. Do not edit.\nvar fs = require('fs')\nvar spawn = require('child_process').spawn\nvar path = require('path')\nvar os = require('os')\n\nvar pidFile = path.join(os.homedir(), '.mobbdev', 'daemon.pid')\nvar HEARTBEAT_STALE_MS = __HEARTBEAT_STALE_MS__\n\ntry {\n var data = JSON.parse(fs.readFileSync(pidFile, 'utf8'))\n if (Date.now() - data.heartbeat > HEARTBEAT_STALE_MS) throw new Error('stale')\n process.kill(data.pid, 0) // throws ESRCH if the process is gone\n} catch (e) {\n var localCli = process.env.MOBBDEV_LOCAL_CLI\n var child = localCli\n ? spawn('node', [localCli, 'claude-code-daemon'], { detached: true, stdio: 'ignore', windowsHide: true })\n : spawn('npx', ['--yes', 'mobbdev@latest', 'claude-code-daemon'], { detached: true, stdio: 'ignore', shell: true, windowsHide: true })\n child.unref()\n}\n";
|
|
@@ -19367,12 +19547,12 @@ async function autoUpgradeMatcherIfStale() {
|
|
|
19367
19547
|
}
|
|
19368
19548
|
}
|
|
19369
19549
|
async function installMobbHooks(options = {}) {
|
|
19370
|
-
console.log(
|
|
19550
|
+
console.log(chalk12.blue("Installing Mobb hooks in Claude Code settings..."));
|
|
19371
19551
|
if (!await claudeSettingsExists()) {
|
|
19372
|
-
console.log(
|
|
19373
|
-
console.log(
|
|
19374
|
-
console.log(
|
|
19375
|
-
console.log(
|
|
19552
|
+
console.log(chalk12.red("\u274C Claude Code settings file not found"));
|
|
19553
|
+
console.log(chalk12.yellow(`Expected location: ${CLAUDE_SETTINGS_PATH}`));
|
|
19554
|
+
console.log(chalk12.yellow("Is Claude Code installed on your system?"));
|
|
19555
|
+
console.log(chalk12.yellow("Please install Claude Code and try again."));
|
|
19376
19556
|
throw new Error(
|
|
19377
19557
|
"Claude Code settings file not found. Is Claude Code installed?"
|
|
19378
19558
|
);
|
|
@@ -19397,7 +19577,7 @@ async function installMobbHooks(options = {}) {
|
|
|
19397
19577
|
if (envVars.length > 0) {
|
|
19398
19578
|
envPrefix = envVars.join(" ");
|
|
19399
19579
|
console.log(
|
|
19400
|
-
|
|
19580
|
+
chalk12.blue(
|
|
19401
19581
|
`Adding environment variables to hook command: ${envVars.join(", ")}`
|
|
19402
19582
|
)
|
|
19403
19583
|
);
|
|
@@ -19418,15 +19598,15 @@ async function installMobbHooks(options = {}) {
|
|
|
19418
19598
|
(hook) => hook.hooks.some((h) => isMobbHookCommand(h.command))
|
|
19419
19599
|
);
|
|
19420
19600
|
if (existingHookIndex >= 0) {
|
|
19421
|
-
console.log(
|
|
19601
|
+
console.log(chalk12.yellow("Mobb hook already exists, updating..."));
|
|
19422
19602
|
settings.hooks.PostToolUse[existingHookIndex] = mobbHookConfig;
|
|
19423
19603
|
} else {
|
|
19424
|
-
console.log(
|
|
19604
|
+
console.log(chalk12.green("Adding new Mobb hook..."));
|
|
19425
19605
|
settings.hooks.PostToolUse.push(mobbHookConfig);
|
|
19426
19606
|
}
|
|
19427
19607
|
await writeClaudeSettings(settings);
|
|
19428
19608
|
console.log(
|
|
19429
|
-
|
|
19609
|
+
chalk12.green(
|
|
19430
19610
|
`\u2705 Mobb hooks ${options.saveEnv ? "and environment variables " : ""}installed successfully in ${CLAUDE_SETTINGS_PATH}`
|
|
19431
19611
|
)
|
|
19432
19612
|
);
|
|
@@ -20395,6 +20575,13 @@ var partitionInteractiveFixes = (fixes) => {
|
|
|
20395
20575
|
|
|
20396
20576
|
// src/mcp/services/McpGQLClient.ts
|
|
20397
20577
|
var MVS_SCAN_ONLY_ERROR = "Mobb Vibe Shield is not available for your organization: it is on Mobb Scan (scan-only), which reports issues but does not generate fixes. Contact support to enable Mobb Fixer.";
|
|
20578
|
+
function issueTouchesFilesFilter(fileFilter) {
|
|
20579
|
+
return {
|
|
20580
|
+
_or: fileFilter.map((path38) => ({
|
|
20581
|
+
codeNodesJson: { nodes: { _contains: [{ path: path38 }] } }
|
|
20582
|
+
}))
|
|
20583
|
+
};
|
|
20584
|
+
}
|
|
20398
20585
|
var McpGQLClient = class extends GQLClient {
|
|
20399
20586
|
constructor(args) {
|
|
20400
20587
|
super({
|
|
@@ -20764,9 +20951,7 @@ var McpGQLClient = class extends GQLClient {
|
|
|
20764
20951
|
}
|
|
20765
20952
|
const filters = {};
|
|
20766
20953
|
if (fileFilter && fileFilter.length > 0) {
|
|
20767
|
-
filters["vulnerabilityReportIssues"] =
|
|
20768
|
-
codeNodes: { path: { _in: fileFilter } }
|
|
20769
|
-
};
|
|
20954
|
+
filters["vulnerabilityReportIssues"] = issueTouchesFilesFilter(fileFilter);
|
|
20770
20955
|
}
|
|
20771
20956
|
const escapedRepoUrl = repoUrl.replace(/[%_\\]/g, (c) => `\\${c}`);
|
|
20772
20957
|
const resp = await this._clientSdk.GetLatestReportByRepoUrl({
|
|
@@ -20818,9 +21003,7 @@ var McpGQLClient = class extends GQLClient {
|
|
|
20818
21003
|
filters["severityText"] = { _in: severity };
|
|
20819
21004
|
}
|
|
20820
21005
|
if (fileFilter && fileFilter.length > 0) {
|
|
20821
|
-
filters["vulnerabilityReportIssues"] =
|
|
20822
|
-
codeNodes: { path: { _in: fileFilter } }
|
|
20823
|
-
};
|
|
21006
|
+
filters["vulnerabilityReportIssues"] = issueTouchesFilesFilter(fileFilter);
|
|
20824
21007
|
}
|
|
20825
21008
|
try {
|
|
20826
21009
|
logDebug("[GraphQL] Calling GetReportFixes query", {
|
|
@@ -28482,32 +28665,32 @@ var mcpHandler = async (_args) => {
|
|
|
28482
28665
|
|
|
28483
28666
|
// src/args/commands/review.ts
|
|
28484
28667
|
import fs27 from "fs";
|
|
28485
|
-
import
|
|
28668
|
+
import chalk13 from "chalk";
|
|
28486
28669
|
function reviewBuilder(yargs2) {
|
|
28487
28670
|
return yargs2.option("f", {
|
|
28488
28671
|
alias: "scan-file",
|
|
28489
28672
|
demandOption: true,
|
|
28490
28673
|
type: "string",
|
|
28491
|
-
describe:
|
|
28674
|
+
describe: chalk13.bold(
|
|
28492
28675
|
"Select the vulnerability report to analyze (Checkmarx, Snyk, Fortify, CodeQL, Sonarqube, Semgrep)"
|
|
28493
28676
|
)
|
|
28494
28677
|
}).option("repo", { ...repoOption, demandOption: true }).option("scanner", { ...scannerOptions, demandOption: true }).option("ref", { ...refOption, demandOption: true }).option("ch", {
|
|
28495
28678
|
alias: "commit-hash",
|
|
28496
|
-
describe:
|
|
28679
|
+
describe: chalk13.bold("Hash of the commit"),
|
|
28497
28680
|
type: "string",
|
|
28498
28681
|
demandOption: true
|
|
28499
28682
|
}).option("mobb-project-name", mobbProjectNameOption).option("api-key", { ...apiKeyOption, demandOption: true }).option("commit-hash", { ...commitHashOption, demandOption: true }).option("github-token", {
|
|
28500
|
-
describe:
|
|
28683
|
+
describe: chalk13.bold("Github action token"),
|
|
28501
28684
|
type: "string",
|
|
28502
28685
|
demandOption: true
|
|
28503
28686
|
}).option("pull-request", {
|
|
28504
28687
|
alias: ["pr", "pr-number", "pr-id"],
|
|
28505
|
-
describe:
|
|
28688
|
+
describe: chalk13.bold("Number of the pull request"),
|
|
28506
28689
|
type: "number",
|
|
28507
28690
|
demandOption: true
|
|
28508
28691
|
}).option("p", {
|
|
28509
28692
|
alias: "src-path",
|
|
28510
|
-
describe:
|
|
28693
|
+
describe: chalk13.bold(
|
|
28511
28694
|
"Path to the repository folder with the source code"
|
|
28512
28695
|
),
|
|
28513
28696
|
type: "string",
|
|
@@ -28520,7 +28703,7 @@ function reviewBuilder(yargs2) {
|
|
|
28520
28703
|
function validateReviewOptions(argv) {
|
|
28521
28704
|
if (!fs27.existsSync(argv.f)) {
|
|
28522
28705
|
throw new CliError(`
|
|
28523
|
-
Can't access ${
|
|
28706
|
+
Can't access ${chalk13.bold(argv.f)}`);
|
|
28524
28707
|
}
|
|
28525
28708
|
validateRepoUrl(argv);
|
|
28526
28709
|
validateReportFileFormat(argv.f);
|
|
@@ -28556,12 +28739,12 @@ async function scanHandler(args) {
|
|
|
28556
28739
|
}
|
|
28557
28740
|
|
|
28558
28741
|
// src/args/commands/scan_skill.ts
|
|
28559
|
-
import
|
|
28742
|
+
import chalk14 from "chalk";
|
|
28560
28743
|
function scanSkillBuilder(args) {
|
|
28561
28744
|
return args.option("url", {
|
|
28562
28745
|
demandOption: true,
|
|
28563
28746
|
type: "string",
|
|
28564
|
-
describe:
|
|
28747
|
+
describe: chalk14.bold(
|
|
28565
28748
|
"URL or local directory of the skill to scan (GitHub repo, ZIP archive, raw SKILL.md, or folder containing SKILL.md)"
|
|
28566
28749
|
)
|
|
28567
28750
|
}).option("api-key", apiKeyOption).option("ci", ciOption).example(
|
|
@@ -28984,7 +29167,7 @@ function processChatStepCodeAction(step) {
|
|
|
28984
29167
|
import fsPromises5 from "fs/promises";
|
|
28985
29168
|
import os19 from "os";
|
|
28986
29169
|
import path37 from "path";
|
|
28987
|
-
import
|
|
29170
|
+
import chalk15 from "chalk";
|
|
28988
29171
|
function getCodeiumHooksPath() {
|
|
28989
29172
|
return path37.join(os19.homedir(), ".codeium", "hooks.json");
|
|
28990
29173
|
}
|
|
@@ -29009,7 +29192,7 @@ async function writeCodeiumHooks(config2) {
|
|
|
29009
29192
|
}
|
|
29010
29193
|
async function installWindsurfHooks(options = {}) {
|
|
29011
29194
|
const hooksPath = getCodeiumHooksPath();
|
|
29012
|
-
console.log(
|
|
29195
|
+
console.log(chalk15.blue("Installing Mobb hooks in Windsurf IntelliJ..."));
|
|
29013
29196
|
const config2 = await readCodeiumHooks();
|
|
29014
29197
|
if (!config2.hooks) {
|
|
29015
29198
|
config2.hooks = {};
|
|
@@ -29029,7 +29212,7 @@ async function installWindsurfHooks(options = {}) {
|
|
|
29029
29212
|
if (envVars.length > 0) {
|
|
29030
29213
|
command = `${envVars.join(" ")} ${command}`;
|
|
29031
29214
|
console.log(
|
|
29032
|
-
|
|
29215
|
+
chalk15.blue(
|
|
29033
29216
|
`Adding environment variables to hook command: ${envVars.join(", ")}`
|
|
29034
29217
|
)
|
|
29035
29218
|
);
|
|
@@ -29043,15 +29226,15 @@ async function installWindsurfHooks(options = {}) {
|
|
|
29043
29226
|
(hook) => hook.command?.includes("mobbdev@latest windsurf-intellij-process-hook")
|
|
29044
29227
|
);
|
|
29045
29228
|
if (existingHookIndex >= 0) {
|
|
29046
|
-
console.log(
|
|
29229
|
+
console.log(chalk15.yellow("Mobb hook already exists, updating..."));
|
|
29047
29230
|
config2.hooks.post_write_code[existingHookIndex] = mobbHook;
|
|
29048
29231
|
} else {
|
|
29049
|
-
console.log(
|
|
29232
|
+
console.log(chalk15.green("Adding new Mobb hook..."));
|
|
29050
29233
|
config2.hooks.post_write_code.push(mobbHook);
|
|
29051
29234
|
}
|
|
29052
29235
|
await writeCodeiumHooks(config2);
|
|
29053
29236
|
console.log(
|
|
29054
|
-
|
|
29237
|
+
chalk15.green(
|
|
29055
29238
|
`\u2705 Mobb hooks ${options.saveEnv ? "and environment variables " : ""}installed successfully in ${hooksPath}`
|
|
29056
29239
|
)
|
|
29057
29240
|
);
|
|
@@ -29101,93 +29284,93 @@ var windsurfIntellijProcessHookHandler = async () => {
|
|
|
29101
29284
|
var parseArgs = async (args) => {
|
|
29102
29285
|
const yargsInstance = yargs(args);
|
|
29103
29286
|
return yargsInstance.updateStrings({
|
|
29104
|
-
"Commands:":
|
|
29105
|
-
"Options:":
|
|
29106
|
-
"Examples:":
|
|
29107
|
-
"Show help":
|
|
29287
|
+
"Commands:": chalk16.yellow.underline.bold("Commands:"),
|
|
29288
|
+
"Options:": chalk16.yellow.underline.bold("Options:"),
|
|
29289
|
+
"Examples:": chalk16.yellow.underline.bold("Examples:"),
|
|
29290
|
+
"Show help": chalk16.bold("Show help")
|
|
29108
29291
|
}).usage(
|
|
29109
|
-
`${
|
|
29292
|
+
`${chalk16.bold(
|
|
29110
29293
|
"\n Bugsy - Trusted, Automatic Vulnerability Fixer \u{1F575}\uFE0F\u200D\u2642\uFE0F\n\n"
|
|
29111
|
-
)} ${
|
|
29112
|
-
$0 ${
|
|
29294
|
+
)} ${chalk16.yellow.underline.bold("Usage:")}
|
|
29295
|
+
$0 ${chalk16.green(
|
|
29113
29296
|
"<command>"
|
|
29114
|
-
)} ${
|
|
29297
|
+
)} ${chalk16.dim("[options]")}
|
|
29115
29298
|
`
|
|
29116
29299
|
).version(false).command(
|
|
29117
29300
|
mobbCliCommand.scan,
|
|
29118
|
-
|
|
29301
|
+
chalk16.bold(
|
|
29119
29302
|
"Scan your code for vulnerabilities, get automated fixes right away."
|
|
29120
29303
|
),
|
|
29121
29304
|
scanBuilder,
|
|
29122
29305
|
scanHandler
|
|
29123
29306
|
).command(
|
|
29124
29307
|
mobbCliCommand.analyze,
|
|
29125
|
-
|
|
29308
|
+
chalk16.bold(
|
|
29126
29309
|
"Provide a code repository, get automated fixes right away. You can also provide a vulnerability report to analyze or have Mobb scan the code for you."
|
|
29127
29310
|
),
|
|
29128
29311
|
analyzeBuilder,
|
|
29129
29312
|
analyzeHandler
|
|
29130
29313
|
).command(
|
|
29131
29314
|
mobbCliCommand.review,
|
|
29132
|
-
|
|
29315
|
+
chalk16.bold(
|
|
29133
29316
|
"Mobb will review your github pull requests and provide comments with fixes "
|
|
29134
29317
|
),
|
|
29135
29318
|
reviewBuilder,
|
|
29136
29319
|
reviewHandler
|
|
29137
29320
|
).command(
|
|
29138
29321
|
mobbCliCommand.addScmToken,
|
|
29139
|
-
|
|
29322
|
+
chalk16.bold(
|
|
29140
29323
|
"Add your SCM (Github, Gitlab, Azure DevOps) token to Mobb to enable automated fixes."
|
|
29141
29324
|
),
|
|
29142
29325
|
addScmTokenBuilder,
|
|
29143
29326
|
addScmTokenHandler
|
|
29144
29327
|
).command(
|
|
29145
29328
|
mobbCliCommand.scanSkill,
|
|
29146
|
-
|
|
29329
|
+
chalk16.bold("Scan an OpenClaw/ClawHub skill for security threats."),
|
|
29147
29330
|
scanSkillBuilder,
|
|
29148
29331
|
scanSkillHandler
|
|
29149
29332
|
).command(
|
|
29150
29333
|
mobbCliCommand.convertToSarif,
|
|
29151
|
-
|
|
29334
|
+
chalk16.bold("Convert an existing SAST report to SARIF format."),
|
|
29152
29335
|
convertToSarifBuilder,
|
|
29153
29336
|
convertToSarifHandler
|
|
29154
29337
|
).command(
|
|
29155
29338
|
mobbCliCommand.mcp,
|
|
29156
|
-
|
|
29339
|
+
chalk16.bold("Launch the MCP (Model Context Protocol) server."),
|
|
29157
29340
|
mcpBuilder,
|
|
29158
29341
|
mcpHandler
|
|
29159
29342
|
).command(
|
|
29160
29343
|
mobbCliCommand.uploadAiBlame,
|
|
29161
|
-
|
|
29344
|
+
chalk16.bold(
|
|
29162
29345
|
"Upload AI Blame inference artifacts (prompt + inference) and finalize them."
|
|
29163
29346
|
),
|
|
29164
29347
|
uploadAiBlameBuilder,
|
|
29165
29348
|
uploadAiBlameCommandHandler
|
|
29166
29349
|
).command(
|
|
29167
29350
|
mobbCliCommand.claudeCodeInstallHook,
|
|
29168
|
-
|
|
29351
|
+
chalk16.bold("Install Claude Code hooks for data collection."),
|
|
29169
29352
|
claudeCodeInstallHookBuilder,
|
|
29170
29353
|
claudeCodeInstallHookHandler
|
|
29171
29354
|
).command(
|
|
29172
29355
|
mobbCliCommand.claudeCodeProcessHook,
|
|
29173
|
-
|
|
29356
|
+
chalk16.bold("Process Claude Code hook data (legacy \u2014 spawns daemon)."),
|
|
29174
29357
|
claudeCodeProcessHookBuilder,
|
|
29175
29358
|
claudeCodeProcessHookHandler
|
|
29176
29359
|
).command(
|
|
29177
29360
|
mobbCliCommand.claudeCodeDaemon,
|
|
29178
|
-
|
|
29361
|
+
chalk16.bold(
|
|
29179
29362
|
"Run the background daemon for Claude Code transcript processing."
|
|
29180
29363
|
),
|
|
29181
29364
|
claudeCodeDaemonBuilder,
|
|
29182
29365
|
claudeCodeDaemonHandler
|
|
29183
29366
|
).command(
|
|
29184
29367
|
mobbCliCommand.windsurfIntellijInstallHook,
|
|
29185
|
-
|
|
29368
|
+
chalk16.bold("Install Windsurf IntelliJ hooks for data collection."),
|
|
29186
29369
|
windsurfIntellijInstallHookBuilder,
|
|
29187
29370
|
windsurfIntellijInstallHookHandler
|
|
29188
29371
|
).command(
|
|
29189
29372
|
mobbCliCommand.windsurfIntellijProcessHook,
|
|
29190
|
-
|
|
29373
|
+
chalk16.bold("Process Windsurf IntelliJ hook data and upload to backend."),
|
|
29191
29374
|
windsurfIntellijProcessHookBuilder,
|
|
29192
29375
|
windsurfIntellijProcessHookHandler
|
|
29193
29376
|
).example(
|
|
@@ -29198,7 +29381,7 @@ var parseArgs = async (args) => {
|
|
|
29198
29381
|
handler() {
|
|
29199
29382
|
yargsInstance.showHelp();
|
|
29200
29383
|
}
|
|
29201
|
-
}).strictOptions().help("h").alias("h", "help").epilog(
|
|
29384
|
+
}).strictOptions().help("h").alias("h", "help").epilog(chalk16.bgBlue("Made with \u2764\uFE0F by Mobb")).showHelpOnFail(true).wrap(Math.min(120, yargsInstance.terminalWidth())).parse();
|
|
29202
29385
|
};
|
|
29203
29386
|
|
|
29204
29387
|
// src/index.ts
|
|
@@ -29214,7 +29397,7 @@ async function run() {
|
|
|
29214
29397
|
} catch (err) {
|
|
29215
29398
|
if (err instanceof CliError) {
|
|
29216
29399
|
console.error(err.message);
|
|
29217
|
-
process.exit(
|
|
29400
|
+
process.exit(err.exitCode);
|
|
29218
29401
|
}
|
|
29219
29402
|
console.error(
|
|
29220
29403
|
"Something went wrong, please try again or contact support if issue persists."
|