mirror of
https://github.com/github/codeql.git
synced 2026-01-29 06:12:58 +01:00
336 lines
11 KiB
Plaintext
336 lines
11 KiB
Plaintext
/**
|
|
* Provides classes for working with NPM module definitions and dependencies.
|
|
*/
|
|
|
|
import javascript
|
|
private import NodeModuleResolutionImpl
|
|
|
|
/** A `package.json` configuration object. */
|
|
class PackageJSON extends JSONObject {
|
|
PackageJSON() {
|
|
this.getJsonFile().getBaseName() = "package.json" and
|
|
this.isTopLevel()
|
|
}
|
|
|
|
/** Gets the name of this package. */
|
|
string getPackageName() { result = this.getPropStringValue("name") }
|
|
|
|
/** Gets the version of this package. */
|
|
string getVersion() { result = this.getPropStringValue("version") }
|
|
|
|
/** Gets the description of this package. */
|
|
string getDescription() { result = this.getPropStringValue("description") }
|
|
|
|
/** Gets the array of keywords for this package. */
|
|
JSONArray getKeywords() { result = this.getPropValue("keywords") }
|
|
|
|
/** Gets a keyword for this package. */
|
|
string getAKeyword() { result = this.getKeywords().getElementStringValue(_) }
|
|
|
|
/** Gets the homepage URL of this package. */
|
|
string getHomepage() { result = this.getPropStringValue("homepage") }
|
|
|
|
/** Gets the bug tracker information of this package. */
|
|
BugTrackerInfo getBugs() { result = this.getPropValue("bugs") }
|
|
|
|
/** Gets the license information of this package. */
|
|
string getLicense() { result = this.getPropStringValue("license") }
|
|
|
|
/** Gets the author information of this package. */
|
|
ContributorInfo getAuthor() { result = this.getPropValue("author") }
|
|
|
|
/** Gets information for a contributor to this package. */
|
|
ContributorInfo getAContributor() {
|
|
result = this.getPropValue("contributors").getElementValue(_)
|
|
}
|
|
|
|
/** Gets the array of files for this package. */
|
|
JSONArray getFiles() { result = this.getPropValue("files") }
|
|
|
|
/** Gets a file for this package. */
|
|
string getAFile() { result = this.getFiles().getElementStringValue(_) }
|
|
|
|
/** Gets the main module of this package. */
|
|
string getMain() { result = MainModulePath::of(this).getValue() }
|
|
|
|
/** Gets the path of a command defined for this package. */
|
|
string getBin(string cmd) {
|
|
cmd = this.getPackageName() and result = this.getPropStringValue("bin")
|
|
or
|
|
result = this.getPropValue("bin").getPropValue(cmd).getStringValue()
|
|
}
|
|
|
|
/** Gets a manual page for this package. */
|
|
string getAManFile() {
|
|
result = this.getPropStringValue("man") or
|
|
result = this.getPropValue("man").getElementValue(_).getStringValue()
|
|
}
|
|
|
|
/** Gets information about the directories of this package. */
|
|
JSONObject getDirectories() { result = this.getPropValue("directories") }
|
|
|
|
/** Gets repository information for this package. */
|
|
RepositoryInfo getRepository() { result = this.getPropValue("repository") }
|
|
|
|
/** Gets information about the scripts of this package. */
|
|
JSONObject getScripts() { result = this.getPropValue("scripts") }
|
|
|
|
/** Gets configuration information for this package. */
|
|
JSONObject getConfig() { result = this.getPropValue("config") }
|
|
|
|
/** Gets the dependencies of this package. */
|
|
PackageDependencies getDependencies() { result = this.getPropValue("dependencies") }
|
|
|
|
/** Gets the development dependencies of this package. */
|
|
PackageDependencies getDevDependencies() { result = this.getPropValue("devDependencies") }
|
|
|
|
/** Gets the peer dependencies of this package. */
|
|
PackageDependencies getPeerDependencies() { result = this.getPropValue("peerDependencies") }
|
|
|
|
/** Gets the bundled dependencies of this package. */
|
|
PackageDependencies getBundledDependencies() {
|
|
result = this.getPropValue("bundledDependencies") or
|
|
result = this.getPropValue("bundleDependencies")
|
|
}
|
|
|
|
/** Gets the optional dependencies of this package. */
|
|
PackageDependencies getOptionalDependencies() {
|
|
result = this.getPropValue("optionalDependencies")
|
|
}
|
|
|
|
/**
|
|
* Gets a JSON object describing a group of dependencies of
|
|
* this package of the kind specified by `depkind`:
|
|
* `""` for normal dependencies, `"dev"` for `devDependencies`,
|
|
* `"bundled"` for `bundledDependencies` and `"opt"` for
|
|
* `optionalDependencies`.
|
|
*/
|
|
PackageDependencies getADependenciesObject(string depkind) {
|
|
result = this.getDependencies() and depkind = ""
|
|
or
|
|
result = this.getDevDependencies() and depkind = "dev"
|
|
or
|
|
result = this.getBundledDependencies() and depkind = "bundled"
|
|
or
|
|
result = this.getOptionalDependencies() and depkind = "opt"
|
|
}
|
|
|
|
/**
|
|
* Holds if this package declares a dependency (including
|
|
* optional, development and bundled dependencies) on the given version
|
|
* of the given package.
|
|
*
|
|
* This does _not_ consider peer dependencies, which are semantically
|
|
* different from the other dependency types.
|
|
*/
|
|
predicate declaresDependency(string pkg, string version) {
|
|
this.getADependenciesObject(_).getADependency(pkg, version)
|
|
}
|
|
|
|
/** Gets the engine dependencies of this package. */
|
|
PackageDependencies getEngines() { result = this.getPropValue("engines") }
|
|
|
|
/** Holds if this package has strict engine requirements. */
|
|
predicate isEngineStrict() { this.getPropValue("engineStrict").(JSONBoolean).getValue() = "true" }
|
|
|
|
/** Gets information about operating systems supported by this package. */
|
|
JSONArray getOSs() { result = this.getPropValue("os") }
|
|
|
|
/** Gets an operating system supported by this package. */
|
|
string getWhitelistedOS() {
|
|
result = this.getOSs().getElementStringValue(_) and
|
|
not result.matches("!%")
|
|
}
|
|
|
|
/** Gets an operating system not supported by this package. */
|
|
string getBlacklistedOS() {
|
|
exists(string str | str = this.getOSs().getElementStringValue(_) |
|
|
result = str.regexpCapture("!(.*)", 1)
|
|
)
|
|
}
|
|
|
|
/** Gets information about platforms supported by this package. */
|
|
JSONArray getCPUs() { result = this.getPropValue("cpu") }
|
|
|
|
/** Gets a platform supported by this package. */
|
|
string getWhitelistedCPU() {
|
|
result = this.getCPUs().getElementStringValue(_) and
|
|
not result.matches("!%")
|
|
}
|
|
|
|
/** Gets a platform not supported by this package. */
|
|
string getBlacklistedCPU() {
|
|
exists(string str | str = this.getCPUs().getElementStringValue(_) |
|
|
result = str.regexpCapture("!(.*)", 1)
|
|
)
|
|
}
|
|
|
|
/** Holds if this package prefers to be installed globally. */
|
|
predicate isPreferGlobal() { this.getPropValue("preferGlobal").(JSONBoolean).getValue() = "true" }
|
|
|
|
/** Holds if this is a private package. */
|
|
predicate isPrivate() { this.getPropValue("private").(JSONBoolean).getValue() = "true" }
|
|
|
|
/** Gets publishing configuration information about this package. */
|
|
JSONValue getPublishConfig() { result = this.getPropValue("publishConfig") }
|
|
|
|
/**
|
|
* Gets the main module of this package.
|
|
*/
|
|
Module getMainModule() {
|
|
result = min(Module m, int prio | m.getFile() = resolveMainModule(this, prio) | m order by prio)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A representation of bug tracker information for an NPM package.
|
|
*/
|
|
class BugTrackerInfo extends JSONValue {
|
|
BugTrackerInfo() {
|
|
exists(PackageJSON pkg | pkg.getPropValue("bugs") = this) and
|
|
(this instanceof JSONObject or this instanceof JSONString)
|
|
}
|
|
|
|
/** Gets the bug tracker URL. */
|
|
string getUrl() {
|
|
result = this.getPropValue("url").getStringValue() or
|
|
result = this.getStringValue()
|
|
}
|
|
|
|
/** Gets the bug reporting email address. */
|
|
string getEmail() { result = this.getPropValue("email").getStringValue() }
|
|
}
|
|
|
|
/**
|
|
* A representation of contributor information for an NPM package.
|
|
*/
|
|
class ContributorInfo extends JSONValue {
|
|
ContributorInfo() {
|
|
exists(PackageJSON pkg |
|
|
this = pkg.getPropValue("author") or
|
|
this = pkg.getPropValue("contributors").getElementValue(_)
|
|
) and
|
|
(this instanceof JSONObject or this instanceof JSONString)
|
|
}
|
|
|
|
/**
|
|
* Gets the `i`th item of information about a contributor, where the first
|
|
* item is their name, the second their email address, and the third their
|
|
* homepage URL.
|
|
*/
|
|
private string parseInfo(int group) {
|
|
result = this.getStringValue().regexpCapture("(.*?)(?: <(.*?)>)?(?: \\((.*)?\\))", group)
|
|
}
|
|
|
|
/** Gets the contributor's name. */
|
|
string getName() {
|
|
result = this.getPropValue("name").getStringValue() or
|
|
result = this.parseInfo(1)
|
|
}
|
|
|
|
/** Gets the contributor's email address. */
|
|
string getEmail() {
|
|
result = this.getPropValue("email").getStringValue() or
|
|
result = this.parseInfo(2)
|
|
}
|
|
|
|
/** Gets the contributor's homepage URL. */
|
|
string getUrl() {
|
|
result = this.getPropValue("url").getStringValue() or
|
|
result = this.parseInfo(3)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A representation of repository information for an NPM package.
|
|
*/
|
|
class RepositoryInfo extends JSONObject {
|
|
RepositoryInfo() { exists(PackageJSON pkg | this = pkg.getPropValue("repository")) }
|
|
|
|
/** Gets the repository type. */
|
|
string getType() { result = this.getPropStringValue("type") }
|
|
|
|
/** Gets the repository URL. */
|
|
string getUrl() { result = this.getPropStringValue("url") }
|
|
}
|
|
|
|
/**
|
|
* A representation of package dependencies for an NPM package.
|
|
*/
|
|
class PackageDependencies extends JSONObject {
|
|
PackageDependencies() {
|
|
exists(PackageJSON pkg, string name |
|
|
name.regexpMatch("(.+D|d)ependencies|engines") and
|
|
this = pkg.getPropValue(name)
|
|
)
|
|
}
|
|
|
|
/** Holds if this package depends on version 'version' of package 'pkg'. */
|
|
predicate getADependency(string pkg, string version) { version = this.getPropStringValue(pkg) }
|
|
}
|
|
|
|
/**
|
|
* An NPM package.
|
|
*/
|
|
class NPMPackage extends @folder {
|
|
/** The `package.json` file of this package. */
|
|
PackageJSON pkg;
|
|
|
|
NPMPackage() { pkg.getJsonFile().getParentContainer() = this }
|
|
|
|
/** Gets a textual representation of this package. */
|
|
string toString() { result = this.(Folder).toString() }
|
|
|
|
/** Gets the full file system path of this package. */
|
|
string getPath() { result = this.(Folder).getAbsolutePath() }
|
|
|
|
/** Gets the `package.json` object of this package. */
|
|
PackageJSON getPackageJSON() { result = pkg }
|
|
|
|
/** Gets the name of this package. */
|
|
string getPackageName() { result = this.getPackageJSON().getPackageName() }
|
|
|
|
/** Gets the `node_modules` folder of this package. */
|
|
Folder getNodeModulesFolder() {
|
|
result.getBaseName() = "node_modules" and
|
|
result.getParentContainer() = this
|
|
}
|
|
|
|
/**
|
|
* Gets a file belonging to this package.
|
|
*
|
|
* We only consider files to belong to the nearest enclosing package,
|
|
* and files inside the `node_modules` folder of a package are not
|
|
* considered to belong to that package.
|
|
*/
|
|
File getAFile() { this = packageInternalParent*(result.getParentContainer()) }
|
|
|
|
/**
|
|
* Gets a Node.js module belonging to this package.
|
|
*
|
|
* We only consider modules to belong to the nearest enclosing package,
|
|
* and modules inside the `node_modules` folder of a package are not
|
|
* considered to belong to that package.
|
|
*/
|
|
Module getAModule() { result.getFile() = this.getAFile() }
|
|
|
|
/**
|
|
* Gets the main module of this package.
|
|
*/
|
|
Module getMainModule() { result = pkg.getMainModule() }
|
|
|
|
/**
|
|
* Holds if this package declares a dependency on version `v` of package `p`.
|
|
*/
|
|
predicate declaresDependency(string p, string v) { pkg.declaresDependency(p, v) }
|
|
}
|
|
|
|
/**
|
|
* Gets the parent folder of `c`, provided that they belong to the same NPM
|
|
* package; that is, `c` must not be a `node_modules` folder.
|
|
*/
|
|
private Folder packageInternalParent(Container c) {
|
|
result = c.getParentContainer() and
|
|
not c.(Folder).getBaseName() = "node_modules"
|
|
}
|