added arborist.js file & support for npm auth token for arborist lib to scan private deps

This commit is contained in:
Sahilb315
2025-04-10 01:10:56 +05:30
parent ed8f9b6d53
commit 2d2f0fdee9
6 changed files with 101 additions and 13 deletions
+6 -2
View File
@@ -49,7 +49,7 @@ func NewNpmCommand() *cobra.Command {
return fmt.Errorf("npm not found: %w", err) return fmt.Errorf("npm not found: %w", err)
} }
return utils.ExecCmd(npmPath, args) return utils.ExecCmd(npmPath, args, []string{})
}, },
} }
return cmd return cmd
@@ -71,7 +71,11 @@ func wrapNpm() error {
Interpreter: "node", Interpreter: "node",
ScriptType: "js", ScriptType: "js",
Args: []string{}, Args: []string{},
Env: map[string]string{
"NPM_AUTH_TOKEN": utils.NpmAuthToken(),
},
}) })
if err != nil { if err != nil {
return fmt.Errorf("failed to extract package info: %w", err) return fmt.Errorf("failed to extract package info: %w", err)
} }
@@ -154,7 +158,7 @@ func wrapNpm() error {
// Install the package and return // Install the package and return
cmdArgs := []string{action, packageName} cmdArgs := []string{action, packageName}
if err = utils.ExecCmd(npmPath, cmdArgs); err != nil { if err = utils.ExecCmd(npmPath, cmdArgs, []string{}); err != nil {
return fmt.Errorf("failed to execute npm command: %w", err) return fmt.Errorf("failed to execute npm command: %w", err)
} }
+10 -4
View File
@@ -69306,11 +69306,11 @@ var require_lib43 = __commonJS({
// arborist.js // arborist.js
var Arborist = require_lib43(); var Arborist = require_lib43();
var fs = require("fs"); var fs = require("fs");
async function getDependencyTree(packageName) { async function getDependencyTree(packageName, authToken2) {
const arb = new Arborist({ const arb = new Arborist({
registry: "https://registry.npmjs.org", registry: "https://registry.npmjs.org",
token: "", token: authToken2,
authToken: "" authToken: authToken2
}); });
try { try {
const idealTree = await arb.buildIdealTree({ const idealTree = await arb.buildIdealTree({
@@ -69337,6 +69337,7 @@ function writeToFile(packages, filename) {
} }
var packageArg = process.argv[2]; var packageArg = process.argv[2];
var outputFile = process.argv[3]; var outputFile = process.argv[3];
var authToken = process.env.NPM_AUTH_TOKEN;
if (!packageArg) { if (!packageArg) {
console.error("Please provide a package name as an argument"); console.error("Please provide a package name as an argument");
process.exit(1); process.exit(1);
@@ -69345,7 +69346,12 @@ if (!outputFile) {
console.error("Please provide an output filename as the second argument"); console.error("Please provide an output filename as the second argument");
process.exit(1); process.exit(1);
} }
getDependencyTree(packageArg).then((packages) => { if (!authToken) {
console.warn(
"NPM token not found. Some private or scoped dependencies may not be included in the scan."
);
}
getDependencyTree(packageArg, authToken).then((packages) => {
writeToFile(packages, outputFile); writeToFile(packages, outputFile);
}).catch((err) => { }).catch((err) => {
console.error("Error:", err); console.error("Error:", err);
+67
View File
@@ -0,0 +1,67 @@
const Arborist = require("@npmcli/arborist");
const fs = require("fs");
async function getDependencyTree(packageName, authToken) {
const arb = new Arborist({
registry: "https://registry.npmjs.org",
token: authToken,
authToken: authToken,
});
try {
const idealTree = await arb.buildIdealTree({
add: [packageName],
});
const packageNames = [];
idealTree.children.forEach((node) => {
packageNames.push(`${node.name}@${node.version}`);
});
return packageNames;
} catch (error) {
console.error(`Failed to fetch dependency tree for ${packageName}:`, error);
return [];
}
}
/**
* Write dependency list to a file
* @param {string[]} packages - List of package dependencies
* @param {string} filename - Output filename
*/
function writeToFile(packages, filename) {
try {
fs.writeFileSync(filename, packages.join("\n"), "utf8");
console.log(`Dependencies written to ${filename}`);
} catch (error) {
console.error(`Failed to write to file ${filename}:`, error);
process.exit(1);
}
}
const packageArg = process.argv[2];
const outputFile = process.argv[3];
const authToken = process.env.NPM_AUTH_TOKEN;
if (!packageArg) {
console.error("Please provide a package name as an argument");
process.exit(1);
}
if (!outputFile) {
console.error("Please provide an output filename as the second argument");
process.exit(1);
}
if (!authToken) {
console.warn(
"NPM token not found. Some private or scoped dependencies may not be included in the scan.",
);
}
getDependencyTree(packageArg, authToken)
.then((packages) => {
writeToFile(packages, outputFile);
})
.catch((err) => {
console.error("Error:", err);
process.exit(1);
});
+11 -6
View File
@@ -11,11 +11,12 @@ import (
// ExtractorOptions holds configuration for running an extractor script // ExtractorOptions holds configuration for running an extractor script
type ExtractorOptions struct { type ExtractorOptions struct {
ScriptContent string // The script content ScriptContent string // The script content
ScriptType string // File extension like "js", "py", etc. ScriptType string // File extension like "js", "py", etc.
Interpreter string // What interpreter to use (e.g., "node", "python") Interpreter string // What interpreter to use (e.g., "node", "python")
PackageName string // Name of the package to analyze PackageName string // Name of the package to analyze
Args []string // Additional arguments to pass to the script Args []string // Additional arguments to pass to the script
Env map[string]string // Environment variables to pass to the script
} }
// RunExtractor extracts an embedded script to a temp file and executes it // RunExtractor extracts an embedded script to a temp file and executes it
@@ -50,7 +51,11 @@ func RunPkgExtractor(opts ExtractorOptions) (string, error) {
// Build the command with all arguments // Build the command with all arguments
cmdArgs := append([]string{scriptFile.Name(), opts.PackageName, outputFile}, opts.Args...) cmdArgs := append([]string{scriptFile.Name(), opts.PackageName, outputFile}, opts.Args...)
if err = utils.ExecCmd(interpreterPath, cmdArgs); err != nil { var env []string
for key, value := range opts.Env {
env = append(env, fmt.Sprintf("%s=%s", key, value))
}
if err = utils.ExecCmd(interpreterPath, cmdArgs, env); err != nil {
return "", err return "", err
} }
+3 -1
View File
@@ -3,11 +3,13 @@ package utils
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"os"
"os/exec" "os/exec"
) )
func ExecCmd(name string, args []string) error { func ExecCmd(name string, args, env []string) error {
cmd := exec.Command(name, args...) cmd := exec.Command(name, args...)
cmd.Env = append(os.Environ(), env...)
var stdout, stderr bytes.Buffer var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout cmd.Stdout = &stdout
+4
View File
@@ -9,3 +9,7 @@ func ApiKey() string {
func TenantDomain() string { func TenantDomain() string {
return os.Getenv("SAFEDEP_TENANT_ID") return os.Getenv("SAFEDEP_TENANT_ID")
} }
func NpmAuthToken() string {
return os.Getenv("NPM_AUTH_TOKEN")
}