mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
added arborist.js file & support for npm auth token for arborist lib to scan private deps
This commit is contained in:
@@ -49,7 +49,7 @@ func NewNpmCommand() *cobra.Command {
|
||||
return fmt.Errorf("npm not found: %w", err)
|
||||
}
|
||||
|
||||
return utils.ExecCmd(npmPath, args)
|
||||
return utils.ExecCmd(npmPath, args, []string{})
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
@@ -71,7 +71,11 @@ func wrapNpm() error {
|
||||
Interpreter: "node",
|
||||
ScriptType: "js",
|
||||
Args: []string{},
|
||||
Env: map[string]string{
|
||||
"NPM_AUTH_TOKEN": utils.NpmAuthToken(),
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to extract package info: %w", err)
|
||||
}
|
||||
@@ -154,7 +158,7 @@ func wrapNpm() error {
|
||||
|
||||
// Install the package and return
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
@@ -69306,11 +69306,11 @@ var require_lib43 = __commonJS({
|
||||
// arborist.js
|
||||
var Arborist = require_lib43();
|
||||
var fs = require("fs");
|
||||
async function getDependencyTree(packageName) {
|
||||
async function getDependencyTree(packageName, authToken2) {
|
||||
const arb = new Arborist({
|
||||
registry: "https://registry.npmjs.org",
|
||||
token: "",
|
||||
authToken: ""
|
||||
token: authToken2,
|
||||
authToken: authToken2
|
||||
});
|
||||
try {
|
||||
const idealTree = await arb.buildIdealTree({
|
||||
@@ -69337,6 +69337,7 @@ function writeToFile(packages, filename) {
|
||||
}
|
||||
var packageArg = process.argv[2];
|
||||
var outputFile = process.argv[3];
|
||||
var authToken = process.env.NPM_AUTH_TOKEN;
|
||||
if (!packageArg) {
|
||||
console.error("Please provide a package name as an argument");
|
||||
process.exit(1);
|
||||
@@ -69345,7 +69346,12 @@ if (!outputFile) {
|
||||
console.error("Please provide an output filename as the second argument");
|
||||
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);
|
||||
}).catch((err) => {
|
||||
console.error("Error:", err);
|
||||
|
||||
@@ -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
@@ -11,11 +11,12 @@ import (
|
||||
|
||||
// ExtractorOptions holds configuration for running an extractor script
|
||||
type ExtractorOptions struct {
|
||||
ScriptContent string // The script content
|
||||
ScriptType string // File extension like "js", "py", etc.
|
||||
Interpreter string // What interpreter to use (e.g., "node", "python")
|
||||
PackageName string // Name of the package to analyze
|
||||
Args []string // Additional arguments to pass to the script
|
||||
ScriptContent string // The script content
|
||||
ScriptType string // File extension like "js", "py", etc.
|
||||
Interpreter string // What interpreter to use (e.g., "node", "python")
|
||||
PackageName string // Name of the package to analyze
|
||||
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
|
||||
@@ -50,7 +51,11 @@ func RunPkgExtractor(opts ExtractorOptions) (string, error) {
|
||||
|
||||
// Build the command with all arguments
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,13 @@ package utils
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func ExecCmd(name string, args []string) error {
|
||||
func ExecCmd(name string, args, env []string) error {
|
||||
cmd := exec.Command(name, args...)
|
||||
cmd.Env = append(os.Environ(), env...)
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
|
||||
@@ -9,3 +9,7 @@ func ApiKey() string {
|
||||
func TenantDomain() string {
|
||||
return os.Getenv("SAFEDEP_TENANT_ID")
|
||||
}
|
||||
|
||||
func NpmAuthToken() string {
|
||||
return os.Getenv("NPM_AUTH_TOKEN")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user