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 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
});
|
||||||
@@ -16,6 +16,7 @@ type ExtractorOptions struct {
|
|||||||
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,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
|
||||||
|
|||||||
@@ -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")
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user