HEX
Server: Apache
System: Linux webd004.cluster130.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64
User: frenchy (106757)
PHP: 7.4.33
Disabled: _dyuweyrj4,_dyuweyrj4r,dl
Upload Files
File: /home/frenchy/www/french-american.org/current/node_modules/snyk-go-plugin/dist/index.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const fs = require("fs");
const path = require("path");
const graphlib = require("graphlib");
const tmp = require("tmp");
const debugLib = require("debug");
const subProcess = require("./sub-process");
const snyk_go_parser_1 = require("snyk-go-parser");
const debug = debugLib('snyk-go-plugin');
const VIRTUAL_ROOT_NODE_ID = '.';
function inspect(root, targetFile, options = {}) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        options.debug ? debugLib.enable('snyk-go-plugin') : debugLib.disable();
        const result = yield Promise.all([
            getMetaData(root, targetFile),
            getDependencies(root, targetFile),
        ]);
        return {
            plugin: result[0],
            package: result[1],
        };
    });
}
exports.inspect = inspect;
function getMetaData(root, targetFile) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const output = yield subProcess.execute('go', ['version'], { cwd: root });
        const versionMatch = /(go\d+\.?\d+?\.?\d*)/.exec(output);
        const runtime = (versionMatch) ? versionMatch[0] : undefined;
        return {
            name: 'snyk-go-plugin',
            runtime,
            targetFile: pathToPosix(targetFile),
        };
    });
}
function createAssets() {
    // path.join calls have to be exactly in this format, needed by "pkg" to build a standalone Snyk CLI binary:
    // https://www.npmjs.com/package/pkg#detecting-assets-in-source-code
    return [
        path.join(__dirname, '../gosrc/resolve-deps.go'),
        path.join(__dirname, '../gosrc/resolver/pkg.go'),
        path.join(__dirname, '../gosrc/resolver/resolver.go'),
        path.join(__dirname, '../gosrc/resolver/dirwalk/dirwalk.go'),
        path.join(__dirname, '../gosrc/resolver/graph/graph.go'),
    ];
}
function writeFile(writeFilePath, contents) {
    const dirPath = path.dirname(writeFilePath);
    if (!fs.existsSync(dirPath)) {
        fs.mkdirSync(dirPath);
    }
    fs.writeFileSync(writeFilePath, contents);
}
function getFilePathRelativeToDumpDir(filePath) {
    let pathParts = filePath.split('\\gosrc\\');
    // Windows
    if (pathParts.length > 1) {
        return pathParts[1];
    }
    // Unix
    pathParts = filePath.split('/gosrc/');
    return pathParts[1];
}
function dumpAllResolveDepsFilesInTempDir(tempDirName) {
    createAssets().forEach((currentReadFilePath) => {
        if (!fs.existsSync(currentReadFilePath)) {
            throw new Error('The file `' + currentReadFilePath + '` is missing');
        }
        const relFilePathToDumpDir = getFilePathRelativeToDumpDir(currentReadFilePath);
        const writeFilePath = path.join(tempDirName, relFilePathToDumpDir);
        const contents = fs.readFileSync(currentReadFilePath);
        writeFile(writeFilePath, contents);
    });
}
const PACKAGE_MANAGER_BY_TARGET = {
    'Gopkg.lock': 'golangdep',
    'vendor.json': 'govendor',
    'go.mod': 'gomodules',
};
const VENDOR_SYNC_CMD_BY_PKG_MANAGER = {
    golangdep: 'dep ensure',
    govendor: 'govendor sync',
    gomodules: 'go mod download',
};
function getDependencies(root, targetFile) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        let tempDirObj;
        const packageManager = pkgManagerByTarget(targetFile);
        if (packageManager === 'gomodules') {
            return buildDepTreeFromImportsAndModules(root);
        }
        try {
            debug('parsing manifest/lockfile', { root, targetFile });
            const config = parseConfig(root, targetFile);
            tempDirObj = tmp.dirSync({
                unsafeCleanup: true,
            });
            dumpAllResolveDepsFilesInTempDir(tempDirObj.name);
            const goResolveTool = path.join(tempDirObj.name, 'resolve-deps.go');
            let ignorePkgsParam;
            if (config.ignoredPkgs && config.ignoredPkgs.length > 0) {
                ignorePkgsParam = '-ignoredPkgs=' + config.ignoredPkgs.join(',');
            }
            const args = ['run', goResolveTool, ignorePkgsParam];
            debug('executing go deps resolver', { cmd: 'go' + args.join(' ') });
            const graphStr = yield subProcess.execute('go', args, { cwd: root });
            tempDirObj.removeCallback();
            debug('loading deps resolver graph output to graphlib', { jsonSize: graphStr.length });
            const graph = graphlib.json.read(JSON.parse(graphStr));
            if (!graphlib.alg.isAcyclic(graph)) {
                throw new Error('Go import cycle detected (not allowed by the Go compiler)');
            }
            // A project can contain several "entry points",
            // i.e. pkgs with no local dependants.
            // To create a tree, we add edges from a "virutal root",
            // to these source nodes.
            const rootNode = graph.node(VIRTUAL_ROOT_NODE_ID);
            if (!rootNode) {
                throw new Error('Failed parsing dependency graph');
            }
            graph.sources().forEach((nodeId) => {
                if (nodeId !== VIRTUAL_ROOT_NODE_ID) {
                    graph.setEdge(VIRTUAL_ROOT_NODE_ID, nodeId);
                }
            });
            const projectRootPath = getProjectRootFromTargetFile(targetFile);
            debug('building dep-tree');
            const pkgsTree = recursivelyBuildPkgTree(graph, rootNode, config.lockedVersions, projectRootPath, {});
            delete pkgsTree._counts;
            pkgsTree.packageFormatVersion = 'golang:0.0.1';
            debug('done building dep-tree', { rootPkgName: pkgsTree.name });
            return pkgsTree;
        }
        catch (error) {
            if (tempDirObj) {
                tempDirObj.removeCallback();
            }
            if (typeof error === 'string') {
                const unresolvedOffset = error.indexOf('Unresolved packages:');
                if (unresolvedOffset !== -1) {
                    throw new Error(error.slice(unresolvedOffset) + '\n' +
                        'Unresolved imports found, please run `' +
                        syncCmdForTarget(targetFile) + '`');
                }
                throw new Error(error);
            }
            throw error;
        }
    });
}
function pkgManagerByTarget(targetFile) {
    const fname = path.basename(targetFile);
    return PACKAGE_MANAGER_BY_TARGET[fname];
}
function syncCmdForTarget(targetFile) {
    return VENDOR_SYNC_CMD_BY_PKG_MANAGER[pkgManagerByTarget(targetFile)];
}
function getProjectRootFromTargetFile(targetFile) {
    const resolved = path.resolve(targetFile);
    const parts = resolved.split(path.sep);
    if (parts[parts.length - 1] === 'Gopkg.lock') {
        return path.dirname(resolved);
    }
    if (parts[parts.length - 1] === 'vendor.json' &&
        parts[parts.length - 2] === 'vendor') {
        return path.dirname(path.dirname(resolved));
    }
    if (parts[parts.length - 1] === 'go.mod') {
        return path.dirname(resolved);
    }
    throw new Error('Unsupported file: ' + targetFile);
}
function recursivelyBuildPkgTree(graph, node, lockedVersions, projectRootPath, totalPackageOccurenceCounter) {
    const isRoot = (node.Name === VIRTUAL_ROOT_NODE_ID);
    const isProjSubpkg = isProjSubpackage(node.Dir, projectRootPath);
    const pkg = {
        name: (isRoot ? node.FullImportPath : node.Name),
        dependencies: {},
    };
    if (!isRoot && isProjSubpkg) {
        pkg._isProjSubpkg = true;
    }
    if (isRoot || isProjSubpkg) {
        pkg.version = '';
    }
    else if (!lockedVersions[pkg.name]) {
        pkg.version = '';
        // TODO: warn or set to "?" ?
    }
    else {
        pkg.version = lockedVersions[pkg.name].version;
    }
    const children = graph.successors(node.Name).sort();
    children.forEach((depName) => {
        // We drop whole dep tree branches for frequently repeatedpackages:
        // this loses some paths, but avoids explosion in result size
        if ((totalPackageOccurenceCounter[depName] || 0) > 10) {
            return;
        }
        const dep = graph.node(depName);
        const child = recursivelyBuildPkgTree(graph, dep, lockedVersions, projectRootPath, totalPackageOccurenceCounter);
        if (child._isProjSubpkg) {
            Object.keys(child.dependencies).forEach((grandChildName) => {
                // We merge all the subpackages of the project into the root project, by transplanting dependencies of the
                // subpackages one level up.
                // This is done to decrease the tree size - and to be similar to other languages, where we are only showing
                // dependencies at the project level, not at the level of individual code sub-directories (which Go packages
                // are, essentially).
                if (!pkg.dependencies[grandChildName]) {
                    pkg.dependencies[grandChildName] = child.dependencies[grandChildName];
                }
            });
            // Even though subpackages are not preserved in the result, we still need protection from combinatorial explosion
            // while scanning the tree.
            totalPackageOccurenceCounter[child.name] = (totalPackageOccurenceCounter[child.name] || 0) + 1;
        }
        else {
            // in case was already added via a grandchild
            if (!pkg.dependencies[child.name]) {
                pkg.dependencies[child.name] = child;
                totalPackageOccurenceCounter[child.name] = (totalPackageOccurenceCounter[child.name] || 0) + 1;
            }
        }
    });
    return pkg;
}
function isProjSubpackage(pkgPath, projectRootPath) {
    if (pkgPath === projectRootPath) {
        return true;
    }
    let root = projectRootPath;
    root =
        (root[root.length - 1] === path.sep) ? root : (root + path.sep);
    if (pkgPath.indexOf(root) !== 0) {
        return false;
    }
    const pkgRelativePath = pkgPath.slice(root.length);
    if (pkgRelativePath.split(path.sep).indexOf('vendor') !== -1) {
        return false;
    }
    return true;
}
function parseConfig(root, targetFile) {
    const pkgManager = pkgManagerByTarget(targetFile);
    debug('detected package-manager:', pkgManager);
    switch (pkgManager) {
        case 'golangdep': {
            try {
                return snyk_go_parser_1.parseGoPkgConfig(getDepManifest(root, targetFile), getDepLock(root, targetFile));
            }
            catch (e) {
                throw (new Error('failed parsing manifest/lock files for Go dep: ' + e.message));
            }
        }
        case 'govendor': {
            try {
                return snyk_go_parser_1.parseGoVendorConfig(getGovendorJson(root, targetFile));
            }
            catch (e) {
                throw (new Error('failed parsing config file for Go Vendor Tool: ' + e.message));
            }
        }
        default: {
            throw new Error('Unsupported file: ' + targetFile);
        }
    }
}
function getDepLock(root, targetFile) {
    return fs.readFileSync(path.join(root, targetFile), 'utf8');
}
function getDepManifest(root, targetFile) {
    const manifestDir = path.dirname(path.join(root, targetFile));
    const manifestPath = path.join(manifestDir, 'Gopkg.toml');
    return fs.readFileSync(manifestPath, 'utf8');
}
// TODO: branch, old Version can be a tag too?
function getGovendorJson(root, targetFile) {
    return fs.readFileSync(path.join(root, targetFile), 'utf8');
}
function pathToPosix(fpath) {
    const parts = fpath.split(path.sep);
    return parts.join(path.posix.sep);
}
// TODO(kyegupov): move to a separate file
function buildDepTreeFromImportsAndModules(root = '.') {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        // TODO(BST-657): parse go.mod file to obtain root module name and go version
        const depTree = {
            name: path.basename(root),
            version: '0.0.0',
            packageFormatVersion: 'golang:0.0.1',
        };
        const goDepsOutput = yield subProcess.execute('go list', ['-json', '-deps', './...'], { cwd: root });
        if (goDepsOutput.includes('matched no packages')) {
            return depTree;
        }
        const goDepsString = `[${goDepsOutput.replace(/}\r?\n{/g, '},{')}]`;
        const goDeps = JSON.parse(goDepsString);
        const packagesByName = {};
        for (const gp of goDeps) {
            packagesByName[gp.ImportPath] = gp; // ImportPath is the fully qualified name
        }
        const localPackages = goDeps.filter((gp) => !gp.DepOnly);
        const localPackageWithMainModule = localPackages
            .find((localPackage) => (localPackage.Module && localPackage.Module.Main));
        if (localPackageWithMainModule && localPackageWithMainModule.Module.Path) {
            depTree.name = localPackageWithMainModule.Module.Path;
        }
        const topLevelDeps = extractAllImports(localPackages);
        buildTree(depTree, topLevelDeps, packagesByName);
        return depTree;
    });
}
exports.buildDepTreeFromImportsAndModules = buildDepTreeFromImportsAndModules;
function buildTree(depTreeNode, depPackages, packagesByName) {
    for (const packageImport of depPackages) {
        let version = 'unknown';
        if (isBuiltinPackage(packageImport)) {
            // We do not track vulns in Go standard library
            continue;
        }
        else if (!packagesByName[packageImport].DepOnly) {
            // Do not include packages of this module
            continue;
        }
        else {
            const pkg = packagesByName[packageImport];
            if (pkg.Module && pkg.Module.Version) {
                version = snyk_go_parser_1.toSnykVersion(snyk_go_parser_1.parseVersion(pkg.Module.Version));
            }
            const newNode = {
                name: packageImport,
                version,
            };
            if (!depTreeNode.dependencies) {
                depTreeNode.dependencies = {};
            }
            depTreeNode.dependencies[packageImport] = newNode;
            if (packagesByName[packageImport].Imports) {
                buildTree(newNode, packagesByName[packageImport].Imports, packagesByName);
            }
        }
    }
}
function extractAllImports(goDeps) {
    const goDepsImports = new Set();
    for (const pkg of goDeps) {
        if (pkg.Imports) {
            for (const imp of pkg.Imports) {
                goDepsImports.add(imp);
            }
        }
    }
    return Array.from(goDepsImports);
}
// Better error message than JSON.parse
function jsonParse(s) {
    try {
        return JSON.parse(s);
    }
    catch (e) {
        e.message = e.message + ', original string: "' + s + '"';
        throw e;
    }
}
exports.jsonParse = jsonParse;
function isBuiltinPackage(pkgName) {
    // Non-builtin packages have domain names in them that contain dots
    return pkgName.indexOf('.') === -1;
}
//# sourceMappingURL=index.js.map