Repository: ossf/package-analysis
Pull request #436 (2022-11-10 04:59:04)

Less refactoring for static analysis
This is the first part of #433, before the `pkgecosystem` refactor, and with some improvements to import ordering


Patch:
diff --git a/cmd/analyze/main.go b/cmd/analyze/main.go
index 786e1b8..645fb14 100644
--- a/cmd/analyze/main.go
+++ b/cmd/analyze/main.go
@@ -7,11 +7,11 @@ import (
 	"os"
 
 	"github.com/ossf/package-analysis/internal/analysis"
-	"github.com/ossf/package-analysis/internal/dynamicanalysis"
 	"github.com/ossf/package-analysis/internal/log"
 	"github.com/ossf/package-analysis/internal/pkgecosystem"
 	"github.com/ossf/package-analysis/internal/resultstore"
 	"github.com/ossf/package-analysis/internal/sandbox"
+	"github.com/ossf/package-analysis/internal/worker"
 )
 
 var (
@@ -55,11 +55,7 @@ func main() {
 		return
 	}
 
-	log.Info("Got request",
-		log.Label("ecosystem", *ecosystem),
-		log.Label("name", *pkgName),
-		log.Label("localPath", *localPkg),
-		log.Label("version", *version))
+	worker.LogRequest(*ecosystem, *pkgName, *version, *localPkg, "")
 
 	pkg, err := manager.ResolvePackage(*pkgName, *version, *localPkg)
 	if err != nil {
@@ -83,10 +79,10 @@ func main() {
 		sbOpts = append(sbOpts, sandbox.Volume(*localPkg, *localPkg))
 	}
 
-	sb := sandbox.New(manager.Image(), sbOpts...)
+	sb := sandbox.New(manager.DynamicAnalysisImage(), sbOpts...)
 	defer sb.Clean()
 
-	results, lastRunPhase, err := analysis.RunDynamicAnalysis(sb, pkg)
+	results, lastRunPhase, err := worker.RunDynamicAnalysis(sb, pkg)
 	if err != nil {
 		log.Fatal("Aborting due to run error", "error", err)
 	}
@@ -103,7 +99,7 @@ func main() {
 
 	// this is only valid if RunDynamicAnalysis() returns nil err
 	lastStatus := results[lastRunPhase].Status
-	if lastStatus != dynamicanalysis.StatusCompleted {
+	if lastStatus != analysis.StatusCompleted {
 		log.Fatal("Analysis phase did not complete successfully",
 			"lastRunPhase", lastRunPhase,
 			"status", lastStatus)
diff --git a/cmd/worker/main.go b/cmd/worker/main.go
index 6549ae0..420fdfa 100644
--- a/cmd/worker/main.go
+++ b/cmd/worker/main.go
@@ -19,11 +19,11 @@ import (
 	_ "gocloud.dev/pubsub/gcppubsub"
 	_ "gocloud.dev/pubsub/kafkapubsub"
 
-	"github.com/ossf/package-analysis/internal/analysis"
 	"github.com/ossf/package-analysis/internal/log"
 	"github.com/ossf/package-analysis/internal/pkgecosystem"
 	"github.com/ossf/package-analysis/internal/resultstore"
 	"github.com/ossf/package-analysis/internal/sandbox"
+	"github.com/ossf/package-analysis/internal/worker"
 )
 
 const (
@@ -67,13 +67,7 @@ func handleMessage(ctx context.Context, msg *pubsub.Message, packagesBucket *blo
 		resultsBucket = resultsBucketOverride
 	}
 
-	log.Info("Got request",
-		log.Label("ecosystem", ecosystem),
-		log.Label("name", name),
-		log.Label("version", version),
-		log.Label("package_path", pkgPath),
-		log.Label("results_bucket_override", resultsBucketOverride),
-	)
+	worker.LogRequest(ecosystem, name, version, pkgPath, resultsBucketOverride)
 
 	localPkgPath := ""
 	sbOpts := []sandbox.Option{
@@ -119,10 +113,10 @@ func handleMessage(ctx context.Context, msg *pubsub.Message, packagesBucket *blo
 		return err
 	}
 
-	sb := sandbox.New(manager.Image(), sbOpts...)
+	sb := sandbox.New(manager.DynamicAnalysisImage(), sbOpts...)
 	defer sb.Clean()
 
-	results, _, err := analysis.RunDynamicAnalysis(sb, pkg)
+	results, _, err := worker.RunDynamicAnalysis(sb, pkg)
 	if err != nil {
 		return err
 	}
diff --git a/internal/analysis/status.go b/internal/analysis/status.go
new file mode 100644
index 0000000..01ddd7c
--- /dev/null
+++ b/internal/analysis/status.go
@@ -0,0 +1,47 @@
+package analysis
+
+import (
+	"encoding/json"
+
+	"github.com/ossf/package-analysis/internal/sandbox"
+)
+
+type Status string
+
+const (
+	// StatusCompleted indicates that the analysis run completed successfully.
+	StatusCompleted = Status("completed")
+
+	// StatusErrorTimeout indicates that the analysis was aborted due to a
+	// timeout.
+	StatusErrorTimeout = Status("error_timeout")
+
+	// StatusErrorAnalysis indicates that the package being analyzed failed
+	// while running the specified command.
+	//
+	// The Stdout and Stderr in the Result should be consulted to understand
+	// further why it failed.
+	StatusErrorAnalysis = Status("error_analysis")
+
+	// StatusErrorOther indicates an error during some part of the analysis
+	// excluding errors covered by other statuses.
+	StatusErrorOther = Status("error_other")
+)
+
+// MarshalJSON implements the json.Marshaler interface.
+func (s Status) MarshalJSON() ([]byte, error) {
+	return json.Marshal(string(s))
+}
+
+func StatusForRunResult(r *sandbox.RunResult) Status {
+	switch r.Status() {
+	case sandbox.RunStatusSuccess:
+		return StatusCompleted
+	case sandbox.RunStatusFailure:
+		return StatusErrorAnalysis
+	case sandbox.RunStatusTimeout:
+		return StatusErrorTimeout
+	default:
+		return StatusErrorOther
+	}
+}
diff --git a/internal/dynamicanalysis/analysis.go b/internal/dynamicanalysis/analysis.go
index 2d8bf45..771afcb 100644
--- a/internal/dynamicanalysis/analysis.go
+++ b/internal/dynamicanalysis/analysis.go
@@ -1,9 +1,9 @@
 package dynamicanalysis
 
 import (
-	"encoding/json"
 	"fmt"
 
+	"github.com/ossf/package-analysis/internal/analysis"
 	"github.com/ossf/package-analysis/internal/dnsanalyzer"
 	"github.com/ossf/package-analysis/internal/log"
 	"github.com/ossf/package-analysis/internal/packetcapture"
@@ -16,46 +16,6 @@ const (
 	maxOutputBytes = 4 * 1024
 )
 
-type Status string
-
-// MarshalJSON implements the json.Marshaler interface.
-func (s Status) MarshalJSON() ([]byte, error) {
-	return json.Marshal(string(s))
-}
-
-const (
-	// StatusCompleted indicates that the analysis run completed successfully.
-	StatusCompleted = Status("completed")
-
-	// StatusErrorTimeout indicates that the analysis was aborted due to a
-	// timeout.
-	StatusErrorTimeout = Status("error_timeout")
-
-	// StatusErrorAnalysis indicates that the package being analyzed failed
-	// while running the specified command.
-	//
-	// The Stdout and Stderr in the Result should be consulted to understand
-	// further why it failed.
-	StatusErrorAnalysis = Status("error_analysis")
-
-	// StatusErrorOther indicates an error during some part of the analysis
-	// excluding errors covered by other statuses.
-	StatusErrorOther = Status("error_other")
-)
-
-func statusForRunResult(r *sandbox.RunResult) Status {
-	switch r.Status() {
-	case sandbox.RunStatusSuccess:
-		return StatusCompleted
-	case sandbox.RunStatusFailure:
-		return StatusErrorAnalysis
-	case sandbox.RunStatusTimeout:
-		return StatusErrorTimeout
-	default:
-		return StatusErrorOther
-	}
-}
-
 type fileResult struct {
 	Path   string
 	Read   bool
@@ -85,8 +45,8 @@ type dnsResult struct {
 }
 
 type Result struct {
-	Status Status
-	Stdout []byte
+	Status   analysis.Status
+	Stdout   []byte
 	Stderr   []byte
 	Files    []fileResult
 	Sockets  []socketResult
@@ -95,11 +55,11 @@ type Result struct {
 }
 
 var (
-	resultError = &Result{Status: StatusErrorOther}
+	resultError = &Result{Status: analysis.StatusErrorOther}
 )
 
 func Run(sb sandbox.Sandbox, args []string) (*Result, error) {
-	log.Info("Running analysis",
+	log.Info("Running dynamic analysis",
 		"args", args)
 
 	log.Debug("Preparing packet capture")
@@ -113,7 +73,7 @@ func Run(sb sandbox.Sandbox, args []string) (*Result, error) {
 	defer pcap.Close()
 
 	// Run the command
-	log.Debug("Running the command",
+	log.Debug("Running dynamic analysis command",
 		"args", args)
 	r, err := sb.Run(args...)
 	if err != nil {
@@ -137,7 +97,7 @@ func Run(sb sandbox.Sandbox, args []string) (*Result, error) {
 	}
 
 	result := Result{
-		Status: statusForRunResult(r),
+		Status: analysis.StatusForRunResult(r),
 		Stdout: lastLines(r.Stdout(), maxOutputLines, maxOutputBytes),
 		Stderr: lastLines(r.Stderr(), maxOutputLines, maxOutputBytes),
 	}
diff --git a/internal/pkgecosystem/ecosystem.go b/internal/pkgecosystem/ecosystem.go
index 7ed4251..258c820 100644
--- a/internal/pkgecosystem/ecosystem.go
+++ b/internal/pkgecosystem/ecosystem.go
@@ -44,7 +44,7 @@ func (p *PkgManager) String() string {
 	return p.name
 }
 
-func (p *PkgManager) Image() string {
+func (p *PkgManager) DynamicAnalysisImage() string {
 	return p.image
 }
 
diff --git a/internal/staticanalysis/obfuscation/detection/compute_signals.go b/internal/staticanalysis/obfuscation/detection/compute_signals.go
index 33734ce..bae8774 100644
--- a/internal/staticanalysis/obfuscation/detection/compute_signals.go
+++ b/internal/staticanalysis/obfuscation/detection/compute_signals.go
@@ -2,12 +2,13 @@ package detection
 
 import (
 	"fmt"
+	"strconv"
+	"strings"
+
 	"github.com/ossf/package-analysis/internal/staticanalysis/obfuscation/stats"
 	"github.com/ossf/package-analysis/internal/staticanalysis/obfuscation/stringentropy"
 	"github.com/ossf/package-analysis/internal/staticanalysis/parsing"
 	"github.com/ossf/package-analysis/internal/staticanalysis/parsing/js"
-	"strconv"
-	"strings"
 )
 
 // characterAnalysis performs analysis on a collection of string symbols, returning:
diff --git a/internal/staticanalysis/obfuscation/stats/sample_statistics.go b/internal/staticanalysis/obfuscation/stats/sample_statistics.go
index 6eeec7a..a09e68f 100644
--- a/internal/staticanalysis/obfuscation/stats/sample_statistics.go
+++ b/internal/staticanalysis/obfuscation/stats/sample_statistics.go
@@ -2,10 +2,12 @@ package stats
 
 import (
 	"fmt"
-	"github.com/ossf/package-analysis/internal/staticanalysis/obfuscation/utils"
+	"math"
+
 	"golang.org/x/exp/constraints"
 	"golang.org/x/exp/slices"
-	"math"
+
+	"github.com/ossf/package-analysis/internal/utils"
 )
 
 type RealNumber interface {
diff --git a/internal/staticanalysis/obfuscation/utils/transform.go b/internal/staticanalysis/obfuscation/utils/transform.go
deleted file mode 100644
index cdf1295..0000000
--- a/internal/staticanalysis/obfuscation/utils/transform.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package utils
-
-func Transform[T, R any](ts []T, fn func(T) R) []R {
-	result := make([]R, len(ts))
-	for i, t := range ts {
-		result[i] = fn(t)
-	}
-	return result
-}
-
-func TransformMap[K comparable, V, R any](m map[K]V, fn func(K, V) R) []R {
-	result := make([]R, len(m))
-	i := 0
-	for k, v := range m {
-		result[i] = fn(k, v)
-		i += 1
-	}
-	return result
-}
diff --git a/internal/staticanalysis/parsing/js/js_parsing.go b/internal/staticanalysis/parsing/js/js_parsing.go
index 21d07b2..5d7df88 100644
--- a/internal/staticanalysis/parsing/js/js_parsing.go
+++ b/internal/staticanalysis/parsing/js/js_parsing.go
@@ -3,14 +3,15 @@ package js
 import (
 	"encoding/json"
 	"fmt"
-	"github.com/ossf/package-analysis/internal/staticanalysis/parsing"
 	"io"
 	"os/exec"
 	"strings"
+
+	"github.com/ossf/package-analysis/internal/staticanalysis/parsing"
 )
 
-// ParserOutputElement represents the output JSON format of the JS parser
-type ParserOutputElement struct {
+// parserOutputElement represents the output JSON format of the JS parser
+type parserOutputElement struct {
 	SymbolType    string         `json:"type"`
 	SymbolSubtype string         `json:"subtype"`
 	Data          any            `json:"data"`
@@ -69,7 +70,7 @@ func ParseJS(parserPath string, filePath string, sourceString string) (*parsing.
 
 	// parse JSON to get results as Go struct
 	decoder := json.NewDecoder(strings.NewReader(parserOutput))
-	var storage []ParserOutputElement
+	var storage []parserOutputElement
 	err = decoder.Decode(&storage)
 	if err != nil {
 		return nil, parserOutput, err
diff --git a/internal/staticanalysis/parsing/string_regexp.go b/internal/staticanalysis/parsing/string_regexp.go
index c48ef11..0c1dfce 100644
--- a/internal/staticanalysis/parsing/string_regexp.go
+++ b/internal/staticanalysis/parsing/string_regexp.go
@@ -1,10 +1,11 @@
 package parsing
 
 import (
-	"github.com/ossf/package-analysis/internal/staticanalysis/obfuscation/utils"
 	"os"
 	"regexp"
 	"strings"
+
+	"github.com/ossf/package-analysis/internal/utils"
 )
 
 // General reference for matching string literals
diff --git a/internal/staticanalysis/obfuscation/utils/float_equals.go b/internal/utils/float_equals.go
similarity index 100%
rename from internal/staticanalysis/obfuscation/utils/float_equals.go
rename to internal/utils/float_equals.go
diff --git a/internal/utils/transform.go b/internal/utils/transform.go
new file mode 100644
index 0000000..9f403e4
--- /dev/null
+++ b/internal/utils/transform.go
@@ -0,0 +1,11 @@
+package utils
+
+// Transform applies the given transform function fn: T -> R to each element t of slice ts
+// and returns a slice containing the corresponding results.
+func Transform[T, R any](ts []T, fn func(T) R) []R {
+	result := make([]R, len(ts))
+	for i, t := range ts {
+		result[i] = fn(t)
+	}
+	return result
+}
diff --git a/internal/worker/logging.go b/internal/worker/logging.go
new file mode 100644
index 0000000..1d733de
--- /dev/null
+++ b/internal/worker/logging.go
@@ -0,0 +1,71 @@
+package worker
+
+import (
+	"github.com/ossf/package-analysis/internal/analysis"
+	"github.com/ossf/package-analysis/internal/log"
+	"github.com/ossf/package-analysis/internal/pkgecosystem"
+)
+
+/*
+NOTE: These strings are referenced externally by infrastructure for dashboard
+reporting / metrics purposes, and so should be changed with care.
+
+See file infra/terraform/metrics/log_metrics.tf
+*/
+const analysisCompleteLogMsg = "Analysis completed sucessfully" // TODO sucessfully -> successfully
+const analysisErrorLogMsg = "Analysis error - analysis"
+const timeoutErrorLogMsg = "Analysis error - timeout"
+const otherErrorLogMsg = "Analysis error - other"
+const runErrorLogMsg = "Analysis run failed"
+const gotRequestLogMsg = "Got request"
+
+// LogDynamicAnalysisError indicates some error happened while attempting to run
+// the package code, which was not caused by the package itself. This means it was
+// not possible to analyse the package properly, and the results are invalid.
+func LogDynamicAnalysisError(pkg *pkgecosystem.Pkg, errorPhase pkgecosystem.RunPhase, err error) {
+	log.Error(runErrorLogMsg,
+		log.Label("ecosystem", pkg.Ecosystem()),
+		log.Label("name", pkg.Name()),
+		log.Label("phase", string(errorPhase)),
+		log.Label("version", pkg.Version()),
+		"error", err)
+}
+
+// LogDynamicAnalysisResult indicates that the package code was run successfully,
+// and what happened when it was run. This may include errors in the analysis
+// of the package, but not errors in the running itself.
+func LogDynamicAnalysisResult(pkg *pkgecosystem.Pkg, finalPhase pkgecosystem.RunPhase, finalStatus analysis.Status) {
+	ecosystem := pkg.Ecosystem()
+	name := pkg.Name()
+	version := pkg.Version()
+	lastPhase := string(finalPhase)
+
+	labels := []interface{}{
+		log.Label("ecosystem", ecosystem),
+		log.Label("name", name),
+		log.Label("version", version),
+		log.Label("last_phase", lastPhase),
+	}
+
+	switch finalStatus {
+	case analysis.StatusCompleted:
+		log.Info(analysisCompleteLogMsg, labels...)
+	case analysis.StatusErrorAnalysis:
+		log.Warn(analysisErrorLogMsg, labels...)
+	case analysis.StatusErrorTimeout:
+		log.Warn(timeoutErrorLogMsg, labels...)
+	case analysis.StatusErrorOther:
+		log.Warn(otherErrorLogMsg, labels...)
+	}
+}
+
+// LogRequest records that a request for analysis was received by the worker.
+func LogRequest(ecosystem, name, version, localPath, resultsBucketOverride string) {
+	log.Info(gotRequestLogMsg,
+		log.Label("ecosystem", ecosystem),
+		log.Label("name", name),
+		log.Label("version", version),
+		log.Label("package_path", localPath),
+		log.Label("results_bucket_override", resultsBucketOverride),
+	)
+}
diff --git a/internal/analysis/rundynamic.go b/internal/worker/rundynamic.go
similarity index 51%
rename from internal/analysis/rundynamic.go
rename to internal/worker/rundynamic.go
index 7fe9063..7aad34a 100644
--- a/internal/analysis/rundynamic.go
+++ b/internal/worker/rundynamic.go
@@ -1,8 +1,8 @@
-package analysis
+package worker
 
 import (
+	"github.com/ossf/package-analysis/internal/analysis"
 	"github.com/ossf/package-analysis/internal/dynamicanalysis"
-	"github.com/ossf/package-analysis/internal/log"
 	"github.com/ossf/package-analysis/internal/pkgecosystem"
 	"github.com/ossf/package-analysis/internal/sandbox"
 )
@@ -38,7 +38,7 @@ func RunDynamicAnalysis(sb sandbox.Sandbox, pkg *pkgecosystem.Pkg) (results Dyna
 
 		results[phase] = result
 
-		if result.Status != dynamicanalysis.StatusCompleted {
+		if result.Status != analysis.StatusCompleted {
 			// Error caused by an issue with the package (probably).
 			// Don't continue with phases if this one did not complete successfully.
 			break
@@ -46,51 +46,11 @@ func RunDynamicAnalysis(sb sandbox.Sandbox, pkg *pkgecosystem.Pkg) (results Dyna
 	}
 
 	if err != nil {
-		logDynamicAnalysisError(pkg, lastRunPhase, err)
+		LogDynamicAnalysisError(pkg, lastRunPhase, err)
 	} else {
 		// Produce a log message for the final status to help generate metrics.
-		logDynamicAnalysisResult(pkg, lastRunPhase, results[lastRunPhase].Status)
+		LogDynamicAnalysisResult(pkg, lastRunPhase, results[lastRunPhase].Status)
 	}
 
 	return results, lastRunPhase, err
 }
-
-// logDynamicAnalysisError indicates some error happened while attempting to run
-// the package code, which was not caused by the package itself. This means it was
-// not possible to analyse the package properly, and the results are invalid.
-func logDynamicAnalysisError(pkg *pkgecosystem.Pkg, errorPhase pkgecosystem.RunPhase, err error) {
-	log.Error("Analysis run failed",
-		log.Label("ecosystem", pkg.Ecosystem()),
-		log.Label("name", pkg.Name()),
-		log.Label("phase", string(errorPhase)),
-		log.Label("version", pkg.Version()),
-		"error", err)
-}
-
-// logDynamicAnalysisResult indicates that the package code was run successfully,
-// and what happened when it was run. This may include errors in the analysis
-// of the package, but not errors in the running itself.
-func logDynamicAnalysisResult(pkg *pkgecosystem.Pkg, finalPhase pkgecosystem.RunPhase, finalStatus dynamicanalysis.Status) {
-	ecosystem := pkg.Ecosystem()
-	name := pkg.Name()
-	version := pkg.Version()
-	lastPhase := string(finalPhase)
-
-	labels := []interface{}{
-		log.Label("ecosystem", ecosystem),
-		log.Label("name", name),
-		log.Label("version", version),
-		log.Label("last_phase", lastPhase),
-	}
-
-	switch finalStatus {
-	case dynamicanalysis.StatusCompleted:
-		log.Info("Analysis completed sucessfully", labels...)
-	case dynamicanalysis.StatusErrorAnalysis:
-		log.Warn("Analysis error - analysis", labels...)
-	case dynamicanalysis.StatusErrorTimeout:
-		log.Warn("Analysis error - timeout", labels...)
-	case dynamicanalysis.StatusErrorOther:
-		log.Warn("Analysis error - other", labels...)
-	}
-}


Test patch:
diff --git a/internal/staticanalysis/obfuscation/detection/compute_signals_test.go b/internal/staticanalysis/obfuscation/detection/compute_signals_test.go
index f1144a4..862088b 100644
--- a/internal/staticanalysis/obfuscation/detection/compute_signals_test.go
+++ b/internal/staticanalysis/obfuscation/detection/compute_signals_test.go
@@ -1,11 +1,12 @@
 package detection
 
 import (
-	"github.com/ossf/package-analysis/internal/staticanalysis/obfuscation/stats"
-	"github.com/ossf/package-analysis/internal/staticanalysis/obfuscation/stringentropy"
-	"github.com/ossf/package-analysis/internal/staticanalysis/obfuscation/utils"
 	"strings"
 	"testing"
+
+	"github.com/ossf/package-analysis/internal/staticanalysis/obfuscation/stats"
+	"github.com/ossf/package-analysis/internal/staticanalysis/obfuscation/stringentropy"
+	"github.com/ossf/package-analysis/internal/utils"
 )
 
 const jsParserPath = "../../parsing/js/babel-parser.js"
@@ -52,7 +53,7 @@ func testSignals(t *testing.T, signals Signals, stringLiterals, identifiers []st
 	}
 }
 
-func TestBasic(t *testing.T) {
+func TestBasicSignals(t *testing.T) {
 	jsSource := `var a = "hello"`
 	rawData, err := CollectData(jsParserPath, "", jsSource, true)
 	if err != nil {
@@ -65,7 +66,7 @@ func TestBasic(t *testing.T) {
 	}
 }
 
-func TestBasic2(t *testing.T) {
+func TestBasicSignals2(t *testing.T) {
 	jsSource := `
 		function test(a, b = 2) {
 			console.log("hello")
diff --git a/internal/staticanalysis/obfuscation/stringentropy/string_entropy_test.go b/internal/staticanalysis/obfuscation/stringentropy/string_entropy_test.go
index 6e54543..2a0466d 100644
--- a/internal/staticanalysis/obfuscation/stringentropy/string_entropy_test.go
+++ b/internal/staticanalysis/obfuscation/stringentropy/string_entropy_test.go
@@ -1,9 +1,10 @@
 package stringentropy
 
 import (
-	"github.com/ossf/package-analysis/internal/staticanalysis/obfuscation/utils"
 	"math"
 	"testing"
+
+	"github.com/ossf/package-analysis/internal/utils"
 )
 
 type entropyTestCase struct {
diff --git a/internal/staticanalysis/parsing/js/js_parsing_test.go b/internal/staticanalysis/parsing/js/js_parsing_test.go
index 5139189..577b5c0 100644
--- a/internal/staticanalysis/parsing/js/js_parsing_test.go
+++ b/internal/staticanalysis/parsing/js/js_parsing_test.go
@@ -1,9 +1,10 @@
 package js
 
 import (
-	"github.com/ossf/package-analysis/internal/staticanalysis/parsing"
 	"reflect"
 	"testing"
+
+	"github.com/ossf/package-analysis/internal/staticanalysis/parsing"
 )
 
 const jsParserPath = "./babel-parser.js"