mirror of
https://github.com/github/codeql.git
synced 2026-05-02 12:15:17 +02:00
Merge remote-tracking branch 'upstream/master' into MoarJQuery
This commit is contained in:
@@ -1,39 +1,126 @@
|
||||
# Code of Conduct
|
||||
## Our Pledge
|
||||
|
||||
This code of conduct outlines expectations for participation in the Semmle open source community, including any open source repositories on GitHub.com, as well as steps for reporting unacceptable behavior. We are committed to providing a welcoming and inspiring community for all.
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
People violating this code of conduct may be banned from the community.
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
Our community strives to:
|
||||
* Be friendly and patient: Remember you might not be communicating in someone else’s primary spoken or programming language, and others may not have your level of understanding.
|
||||
* Be welcoming: Our community welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, color, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.
|
||||
* Be respectful: We are a world-wide community of professionals, and we conduct ourselves professionally. Disagreement is no excuse for poor behavior and poor manners. Disrespectful and unacceptable behavior includes, but is not limited to:
|
||||
* Violent threats or language.
|
||||
* Discriminatory or derogatory jokes and language.
|
||||
* Posting sexually explicit or violent material.
|
||||
* Posting, or threatening to post, people’s personally identifying information (“doxing”).
|
||||
* Insults, especially those using discriminatory terms or slurs.
|
||||
* Behavior that could be perceived as sexual attention.
|
||||
* Advocating for or encouraging any of the above behaviors.
|
||||
* Understand disagreements: Disagreements, both social and technical, are useful learning opportunities. Seek to understand others’ viewpoints and resolve differences constructively.
|
||||
## Our Standards
|
||||
|
||||
This code is not exhaustive or complete. It serves to capture our common understanding of a productive, collaborative environment. We expect the code to be followed in spirit as much as in the letter.
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
# Scope
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
This code of conduct applies to all repositories and communities for Semmle open source projects, regardless of whether or not the repository explicitly calls out its use of this code. The code also applies in public spaces when an individual is representing the Semmle open source community. Examples include using an official project email address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
# Reporting Code of Conduct Issues
|
||||
We encourage members of the community to resolve issues on their own whenever possible. This builds a broader and deeper understanding and ultimately a healthier interaction. In the event that an issue cannot be resolved locally, please feel free to report your concerns by contacting code-of-conduct@semmle.com.
|
||||
In your report please include:
|
||||
* Your contact information.
|
||||
* Names (real, usernames or pseudonyms) of any individuals involved. If there are additional witnesses, please include them as well.
|
||||
* Your account of what occurred, and if you believe the incident is ongoing. If there is a publicly available record (e.g. a mailing list archive or a public chat log), please include a link or attachment.
|
||||
* Any additional information that may be helpful.
|
||||
## Enforcement Responsibilities
|
||||
|
||||
All reports will be reviewed by a multi-person team and will result in a response that is deemed necessary and appropriate to the circumstances. Where additional perspectives are needed, the team may seek insight from others with relevant expertise or experience. The confidentiality of the person reporting the incident will be kept at all times. Involved parties are never part of the review team.
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Anyone asked to stop unacceptable behavior is expected to comply immediately. If an individual engages in unacceptable behavior, the review team may take any action they deem appropriate, including a permanent ban from the community.
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
*This text is licensed under the [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/) license. It is based on a template established by the [TODO Group](http://todogroup.org/) and variants thereof used by numerous other large communities (e.g., [Microsoft](https://microsoft.github.io/codeofconduct/), [Facebook](https://code.fb.com/codeofconduct/), [Yahoo](https://yahoo.github.io/codeofconduct), [Twitter](https://github.com/twitter/code-of-conduct), [GitHub](https://blog.github.com/2015-07-20-adopting-the-open-code-of-conduct/)) and the Scope section from the [Contributor Covenant version 1.4](http://contributor-covenant.org/version/1/4/).*
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
opensource@github.com.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
## General improvements
|
||||
|
||||
* Support for the following frameworks and libraries has been improved:
|
||||
- [jGrowl](https://github.com/stanlemon/jGrowl)
|
||||
- [jQuery](https://jquery.com/)
|
||||
|
||||
## New queries
|
||||
|
||||
@@ -12,12 +12,12 @@ abstract class Assertion extends Locatable {
|
||||
}
|
||||
|
||||
/**
|
||||
* A libc assert, as defined in assert.h. A macro with the head
|
||||
* "assert(expr)" that expands to a conditional expression which
|
||||
* may terminate the program.
|
||||
* A libc assert, as defined in assert.h. A macro with a head
|
||||
* that matches the prefix "assert(", and expands to a conditional
|
||||
* expression which may terminate the program.
|
||||
*/
|
||||
class LibcAssert extends MacroInvocation, Assertion {
|
||||
LibcAssert() { this.getMacro().getHead() = "assert(expr)" }
|
||||
LibcAssert() { this.getMacro().getHead().matches("assert(%") }
|
||||
|
||||
override Expr getAsserted() {
|
||||
exists(ConditionalExpr ce | this.getAGeneratedElement() = ce | result = ce.getCondition())
|
||||
|
||||
@@ -145,8 +145,6 @@ class HexLiteral extends Literal {
|
||||
|
||||
/**
|
||||
* A C/C++ aggregate literal.
|
||||
*
|
||||
* For example:
|
||||
*/
|
||||
class AggregateLiteral extends Expr, @aggregateliteral {
|
||||
override string getCanonicalQLClass() { result = "AggregateLiteral" }
|
||||
|
||||
325
javascript/ql/src/experimental/poi/PoI.qll
Normal file
325
javascript/ql/src/experimental/poi/PoI.qll
Normal file
@@ -0,0 +1,325 @@
|
||||
/**
|
||||
* Provides classes and predicates for discovering points of interest
|
||||
* in an unknown code base.
|
||||
*
|
||||
* To use this module, subclass the
|
||||
* `ActivePoI` class, override *one* of its `is` predicates, and use
|
||||
* `alertQuery` as a `@kind problem` query . This will present
|
||||
* the desired points of interest as alerts that are easily browsable
|
||||
* in a codeql IDE. By itself, this is no different from an ordinary
|
||||
* query, but the strength of this module lies in its extensibility
|
||||
* and standard library:
|
||||
*
|
||||
* - points of interest can be added, removed and mixed seamlessly
|
||||
* - this module comes with a collection of standard points of interest (see `StandardPoIs`)
|
||||
*
|
||||
* A global configuration for the points of interest (see
|
||||
* `PoIConfiguration`) can be used to easily manage multiple points of
|
||||
* interests, and to restrict the points of interest to specific
|
||||
* corners of the code base.
|
||||
*
|
||||
* Below is an example use of this module that will produce an alert
|
||||
* for each route handler and route handler setup in a file named
|
||||
* "server-core.js". The route setup alerts will contain a link to its
|
||||
* associated route handler.
|
||||
*
|
||||
* ```
|
||||
* /**
|
||||
* * @kind problem
|
||||
* *\/
|
||||
*
|
||||
* import PoI
|
||||
*
|
||||
* class Configuration extends PoIConfiguration {
|
||||
* Configuration() { this = "Configuration" }
|
||||
*
|
||||
* override predicate shown(DataFlow::Node n) { n.getFile().getBaseName() = "server-core.js" }
|
||||
* }
|
||||
*
|
||||
* class RouteHandlerPoI extends ActivePoI {
|
||||
* RouteHandlerPoI() { this = "RouteHandlerPoI" }
|
||||
* override predicate is(DataFlow::Node l0) { l0 instanceof Express::RouteHandler }
|
||||
* }
|
||||
*
|
||||
* class RouteSetupAndRouteHandlerPoI extends ActivePoI {
|
||||
* RouteSetupAndRouteHandlerPoI() { this = "RouteSetupAndRouteHandlerPoI" }
|
||||
*
|
||||
* override predicate is(DataFlow::Node l0, DataFlow::Node l1, string t1) {
|
||||
* l0.asExpr().(Express::RouteSetup).getARouteHandler() = l1 and t1 = "routehandler"
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* query predicate problems = alertQuery/6;
|
||||
* ```
|
||||
*/
|
||||
|
||||
import javascript
|
||||
private import DataFlow
|
||||
private import filters.ClassifyFiles
|
||||
private import semmle.javascript.RestrictedLocations
|
||||
|
||||
/**
|
||||
* Provides often used points of interest.
|
||||
*
|
||||
* Note that these points of interest should not extend
|
||||
* `ActivePoI`, and that they can be enabled on
|
||||
* demand like this:
|
||||
*
|
||||
* ```
|
||||
* class MyPoI extends ServerRelatedPoI, ActivePoI {}
|
||||
* ```
|
||||
*/
|
||||
private module StandardPoIs {
|
||||
/**
|
||||
* An unpromoted route setup candidate.
|
||||
*/
|
||||
class UnpromotedRouteSetupPoI extends PoI {
|
||||
UnpromotedRouteSetupPoI() { this = "UnpromotedRouteSetupPoI" }
|
||||
|
||||
override predicate is(Node l0) {
|
||||
l0 instanceof HTTP::RouteSetupCandidate and not l0.asExpr() instanceof HTTP::RouteSetup
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An unpromoted route handler candidate.
|
||||
*/
|
||||
class UnpromotedRouteHandlerPoI extends PoI {
|
||||
UnpromotedRouteHandlerPoI() { this = "UnpromotedRouteHandlerPoI" }
|
||||
|
||||
override predicate is(Node l0) {
|
||||
l0 instanceof HTTP::RouteHandlerCandidate and not l0 instanceof HTTP::RouteHandler
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An unpromoted route handler candidate, with explanatory data flow information.
|
||||
*/
|
||||
class UnpromotedRouteHandlerWithFlowPoI extends PoI {
|
||||
UnpromotedRouteHandlerWithFlowPoI() { this = "UnpromotedRouteHandlerWithFlowPoI" }
|
||||
|
||||
private DataFlow::SourceNode track(HTTP::RouteHandlerCandidate cand, DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = cand
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = track(cand, t2).track(t2, t))
|
||||
}
|
||||
|
||||
override predicate is(Node l0, Node l1, string t1) {
|
||||
l0 instanceof HTTP::RouteHandlerCandidate and
|
||||
not l0 instanceof HTTP::RouteHandler and
|
||||
l1 = track(l0, TypeTracker::end()) and
|
||||
(if l1 = l0 then t1 = "ends here" else t1 = "starts/ends here")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A callee that is unknown.
|
||||
*/
|
||||
class UnknownCalleePoI extends PoI {
|
||||
UnknownCalleePoI() { this = "UnknownCalleePoI" }
|
||||
|
||||
override predicate is(Node l0) {
|
||||
exists(InvokeNode invk | l0 = invk.getCalleeNode() and not exists(invk.getACallee()))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A source of remote flow.
|
||||
*/
|
||||
class RemoteFlowSourcePoI extends PoI {
|
||||
RemoteFlowSourcePoI() { this = "RemoteFlowSourcePoI" }
|
||||
|
||||
override predicate is(Node l0) { l0 instanceof RemoteFlowSource }
|
||||
}
|
||||
|
||||
/**
|
||||
* A "source" for any active configuration.
|
||||
*/
|
||||
class SourcePoI extends PoI {
|
||||
SourcePoI() { this = "SourcePoI" }
|
||||
|
||||
override predicate is(Node l0) {
|
||||
exists(Configuration cfg | cfg.isSource(l0) or cfg.isSource(l0, _))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A "sink" for any active configuration.
|
||||
*/
|
||||
class SinkPoI extends PoI {
|
||||
SinkPoI() { this = "SinkPoI" }
|
||||
|
||||
override predicate is(Node l0) {
|
||||
exists(Configuration cfg | cfg.isSink(l0) or cfg.isSink(l0, _))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A "barrier" for any active configuration.
|
||||
*/
|
||||
class BarrierPoI extends PoI {
|
||||
BarrierPoI() { this = "BarrierPoI" }
|
||||
|
||||
override predicate is(Node l0) {
|
||||
exists(Configuration cfg |
|
||||
cfg.isBarrier(l0) or
|
||||
cfg.isBarrierEdge(l0, _) or
|
||||
cfg.isBarrierEdge(l0, _, _) or
|
||||
cfg.isLabeledBarrier(l0, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides groups of often used points of interest.
|
||||
*/
|
||||
module StandardPoIGroups {
|
||||
/**
|
||||
* A server-related point of interest.
|
||||
*/
|
||||
class ServerRelatedPoI extends PoI {
|
||||
ServerRelatedPoI() {
|
||||
this instanceof UnpromotedRouteSetupPoI or
|
||||
this instanceof UnpromotedRouteHandlerPoI or
|
||||
this instanceof UnpromotedRouteHandlerWithFlowPoI
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration-related point of interest.
|
||||
*/
|
||||
class DataFlowConfigurationPoI extends PoI {
|
||||
DataFlowConfigurationPoI() {
|
||||
this instanceof SourcePoI or
|
||||
this instanceof SinkPoI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import StandardPoIGroups
|
||||
}
|
||||
|
||||
import StandardPoIs
|
||||
|
||||
/**
|
||||
* A tagging interface for a custom point of interest that should be
|
||||
* enabled in the absence of an explicit
|
||||
* `PoIConfiguration::enabled/1`.
|
||||
*/
|
||||
abstract class ActivePoI extends PoI {
|
||||
bindingset[this]
|
||||
ActivePoI() { any() }
|
||||
}
|
||||
|
||||
private module PoIConfigDefaults {
|
||||
predicate enabled(PoI poi) { poi instanceof ActivePoI }
|
||||
|
||||
predicate shown(Node n) { not classify(n.getFile(), _) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration for the points of interest to display.
|
||||
*/
|
||||
abstract class PoIConfiguration extends string {
|
||||
bindingset[this]
|
||||
PoIConfiguration() { any() }
|
||||
|
||||
/**
|
||||
* Holds if the points of interest from `poi` should be shown.
|
||||
*/
|
||||
predicate enabled(PoI poi) { PoIConfigDefaults::enabled(poi) }
|
||||
|
||||
/**
|
||||
* Holds if the points of interest `n` should be shown.
|
||||
*/
|
||||
predicate shown(Node n) { PoIConfigDefaults::shown(n) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A class of points of interest.
|
||||
*
|
||||
* Note that only one of the `is/1`, `is/3`, `is/5` methods should
|
||||
* be overridden, as two overrides will degrade the alert UI
|
||||
* slightly.
|
||||
*/
|
||||
abstract class PoI extends string {
|
||||
bindingset[this]
|
||||
PoI() { any() }
|
||||
|
||||
/**
|
||||
* Holds if `l0` is a point of interest.
|
||||
*/
|
||||
predicate is(Node l0) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `l0` is a point of interest, with `l1` as an auxiliary location described by `t1`.
|
||||
*/
|
||||
predicate is(Node l0, Node l1, string t1) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `l0` is a point of interest, with `l1` and `l2` as auxiliary locations described by `t1` and `t2`.
|
||||
*/
|
||||
predicate is(Node l0, Node l1, string t1, Node l2, string t2) { none() }
|
||||
|
||||
/**
|
||||
* Gets the message format for the point of interest.
|
||||
*/
|
||||
string getFormat() {
|
||||
is(_) and result = ""
|
||||
or
|
||||
is(_, _, _) and result = "$@"
|
||||
or
|
||||
is(_, _, _, _, _) and result = "$@ $@"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An alert query for a point of interest.
|
||||
*
|
||||
* Should be used as:
|
||||
*
|
||||
* ```
|
||||
* query predicate problems = alertQuery/6;
|
||||
* ```
|
||||
*
|
||||
* Or alternatively:
|
||||
*
|
||||
* ```
|
||||
* from Locatable l1line, string msg, Node l2, string s2, Node l3, string s3
|
||||
* where alertQuery(l1line, msg, l2, s2, l3, s3)
|
||||
* select l1line, msg, l2, s2, l3, s3
|
||||
* ```
|
||||
*
|
||||
* Note that some points of interest do not have auxiliary
|
||||
* locations, so `l2`,`l3`, `s2`, `s3` may have placeholder values.
|
||||
*/
|
||||
predicate alertQuery(Locatable l1line, string msg, Node l2, string s2, Node l3, string s3) {
|
||||
exists(PoI poi, Node l1, string m |
|
||||
l1.getAstNode().(FirstLineOf) = l1line and
|
||||
(
|
||||
not exists(PoIConfiguration cfg) and
|
||||
PoIConfigDefaults::enabled(poi) and
|
||||
PoIConfigDefaults::shown(l1)
|
||||
or
|
||||
exists(PoIConfiguration cfg |
|
||||
cfg.enabled(poi) and
|
||||
cfg.shown(l1)
|
||||
)
|
||||
) and
|
||||
m = poi.getFormat() and
|
||||
if m = "" then msg = poi else msg = poi + ": " + m
|
||||
|
|
||||
poi.is(l1) and
|
||||
l1 = l2 and
|
||||
s2 = "irrelevant" and
|
||||
l1 = l3 and
|
||||
s3 = "irrelevant"
|
||||
or
|
||||
poi.is(l1, l2, s2) and
|
||||
l1 = l3 and
|
||||
s3 = "irrelevant"
|
||||
or
|
||||
poi.is(l1, l2, s2, l3, s3)
|
||||
)
|
||||
}
|
||||
@@ -7,85 +7,8 @@
|
||||
* @id js/file-classifier
|
||||
*/
|
||||
|
||||
import semmle.javascript.GeneratedCode
|
||||
import semmle.javascript.frameworks.Testing
|
||||
import semmle.javascript.frameworks.Templating
|
||||
import semmle.javascript.dependencies.FrameworkLibraries
|
||||
|
||||
/**
|
||||
* Holds if `e` may be caused by parsing a template file as plain HTML or JavaScript.
|
||||
*
|
||||
* We use two heuristics: check for the presence of a known template delimiter preceding
|
||||
* the error on the same line, and check whether the file name contains `template` or
|
||||
* `templates`.
|
||||
*/
|
||||
predicate maybeCausedByTemplate(JSParseError e) {
|
||||
exists(File f | f = e.getFile() |
|
||||
e.getLine().indexOf(Templating::getADelimiter()) <= e.getLocation().getStartColumn()
|
||||
or
|
||||
f.getAbsolutePath().regexpMatch("(?i).*\\btemplates?\\b.*")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is an expression in the form `o.p1.p2.p3....pn`.
|
||||
*/
|
||||
private predicate isNestedDotExpr(DotExpr e) {
|
||||
e.getBase() instanceof VarAccess or
|
||||
isNestedDotExpr(e.getBase())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `tl` only contains variable declarations and field reads.
|
||||
*/
|
||||
private predicate looksLikeExterns(TopLevel tl) {
|
||||
forex(Stmt s | s.getParent() = tl |
|
||||
exists(VarDeclStmt vds | vds = s |
|
||||
forall(VariableDeclarator vd | vd = vds.getADecl() | not exists(vd.getInit()))
|
||||
)
|
||||
or
|
||||
isNestedDotExpr(s.(ExprStmt).getExpr())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `f` is classified as belonging to `category`.
|
||||
*
|
||||
* There are currently four categories:
|
||||
* - `"generated"`: `f` contains generated or minified code;
|
||||
* - `"test"`: `f` contains test code;
|
||||
* - `"externs"`: `f` contains externs declarations;
|
||||
* - `"library"`: `f` contains library code;
|
||||
* - `"template"`: `f` contains template code.
|
||||
*/
|
||||
predicate classify(File f, string category) {
|
||||
isGenerated(f.getATopLevel()) and category = "generated"
|
||||
or
|
||||
(
|
||||
exists(Test t | t.getFile() = f)
|
||||
or
|
||||
exists(string stemExt | stemExt = "test" or stemExt = "spec" |
|
||||
f = getTestFile(any(File orig), stemExt)
|
||||
)
|
||||
or
|
||||
f.getAbsolutePath().regexpMatch(".*/__(mocks|tests)__/.*")
|
||||
) and
|
||||
category = "test"
|
||||
or
|
||||
(f.getATopLevel().isExterns() or looksLikeExterns(f.getATopLevel())) and
|
||||
category = "externs"
|
||||
or
|
||||
f.getATopLevel() instanceof FrameworkLibraryInstance and category = "library"
|
||||
or
|
||||
exists(JSParseError err | maybeCausedByTemplate(err) |
|
||||
f = err.getFile() and category = "template"
|
||||
)
|
||||
or
|
||||
// Polymer templates
|
||||
exists(HTML::Element elt | elt.getName() = "template" |
|
||||
f = elt.getFile() and category = "template"
|
||||
)
|
||||
}
|
||||
import javascript
|
||||
import ClassifyFiles
|
||||
|
||||
from File f, string category
|
||||
where classify(f, category)
|
||||
|
||||
85
javascript/ql/src/filters/ClassifyFiles.qll
Normal file
85
javascript/ql/src/filters/ClassifyFiles.qll
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Provides classes and predicates for classifying files as containing
|
||||
* generated code, test code, externs declarations, library code or
|
||||
* template code.
|
||||
*/
|
||||
|
||||
import semmle.javascript.GeneratedCode
|
||||
import semmle.javascript.frameworks.Testing
|
||||
import semmle.javascript.frameworks.Templating
|
||||
import semmle.javascript.dependencies.FrameworkLibraries
|
||||
|
||||
/**
|
||||
* Holds if `e` may be caused by parsing a template file as plain HTML or JavaScript.
|
||||
*
|
||||
* We use two heuristics: check for the presence of a known template delimiter preceding
|
||||
* the error on the same line, and check whether the file name contains `template` or
|
||||
* `templates`.
|
||||
*/
|
||||
predicate maybeCausedByTemplate(JSParseError e) {
|
||||
exists(File f | f = e.getFile() |
|
||||
e.getLine().indexOf(Templating::getADelimiter()) <= e.getLocation().getStartColumn()
|
||||
or
|
||||
f.getAbsolutePath().regexpMatch("(?i).*\\btemplates?\\b.*")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is an expression in the form `o.p1.p2.p3....pn`.
|
||||
*/
|
||||
private predicate isNestedDotExpr(DotExpr e) {
|
||||
e.getBase() instanceof VarAccess or
|
||||
isNestedDotExpr(e.getBase())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `tl` only contains variable declarations and field reads.
|
||||
*/
|
||||
private predicate looksLikeExterns(TopLevel tl) {
|
||||
forex(Stmt s | s.getParent() = tl |
|
||||
exists(VarDeclStmt vds | vds = s |
|
||||
forall(VariableDeclarator vd | vd = vds.getADecl() | not exists(vd.getInit()))
|
||||
)
|
||||
or
|
||||
isNestedDotExpr(s.(ExprStmt).getExpr())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `f` is classified as belonging to `category`.
|
||||
*
|
||||
* There are currently four categories:
|
||||
* - `"generated"`: `f` contains generated or minified code;
|
||||
* - `"test"`: `f` contains test code;
|
||||
* - `"externs"`: `f` contains externs declarations;
|
||||
* - `"library"`: `f` contains library code;
|
||||
* - `"template"`: `f` contains template code.
|
||||
*/
|
||||
predicate classify(File f, string category) {
|
||||
isGenerated(f.getATopLevel()) and category = "generated"
|
||||
or
|
||||
(
|
||||
exists(Test t | t.getFile() = f)
|
||||
or
|
||||
exists(string stemExt | stemExt = "test" or stemExt = "spec" |
|
||||
f = getTestFile(any(File orig), stemExt)
|
||||
)
|
||||
or
|
||||
f.getAbsolutePath().regexpMatch(".*/__(mocks|tests)__/.*")
|
||||
) and
|
||||
category = "test"
|
||||
or
|
||||
(f.getATopLevel().isExterns() or looksLikeExterns(f.getATopLevel())) and
|
||||
category = "externs"
|
||||
or
|
||||
f.getATopLevel() instanceof FrameworkLibraryInstance and category = "library"
|
||||
or
|
||||
exists(JSParseError err | maybeCausedByTemplate(err) |
|
||||
f = err.getFile() and category = "template"
|
||||
)
|
||||
or
|
||||
// Polymer templates
|
||||
exists(HTML::Element elt | elt.getName() = "template" |
|
||||
f = elt.getFile() and category = "template"
|
||||
)
|
||||
}
|
||||
@@ -99,6 +99,8 @@ module DomBasedXss {
|
||||
this = any(Typeahead::TypeaheadSuggestionFunction f).getAReturn()
|
||||
or
|
||||
this = any(Handlebars::SafeString s).getAnArgument()
|
||||
or
|
||||
this = any(JQuery::MethodCall call | call.getMethodName() = "jGrowl").getArgument(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
| tst.js:16:15:16:25 | req.query.x | SourcePoI | tst.js:16:15:16:25 | req.query.x | irrelevant | tst.js:16:15:16:25 | req.query.x | irrelevant |
|
||||
| tst.js:17:11:17:21 | req.query.x | SinkPoI | tst.js:17:11:17:21 | req.query.x | irrelevant | tst.js:17:11:17:21 | req.query.x | irrelevant |
|
||||
| tst.js:17:11:17:21 | req.query.x | SourcePoI | tst.js:17:11:17:21 | req.query.x | irrelevant | tst.js:17:11:17:21 | req.query.x | irrelevant |
|
||||
| tst.js:18:12:18:22 | req.query.x | SourcePoI | tst.js:18:12:18:22 | req.query.x | irrelevant | tst.js:18:12:18:22 | req.query.x | irrelevant |
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @kind problem
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import experimental.poi.PoI
|
||||
import semmle.javascript.security.dataflow.CommandInjection
|
||||
import semmle.javascript.security.dataflow.IndirectCommandInjection
|
||||
import semmle.javascript.security.dataflow.ShellCommandInjectionFromEnvironment
|
||||
|
||||
class MyDataFlowConfigurationPoIs extends DataFlowConfigurationPoI, ActivePoI { }
|
||||
|
||||
query predicate problems = alertQuery/6;
|
||||
@@ -0,0 +1,3 @@
|
||||
| tst.js:6:1:6:16 | (req, res) => 42 | UnpromotedRouteHandlerPoI | tst.js:6:1:6:16 | (req, res) => 42 | irrelevant | tst.js:6:1:6:16 | (req, res) => 42 | irrelevant |
|
||||
| tst.js:6:1:6:16 | (req, res) => 42 | UnpromotedRouteHandlerWithFlowPoI: $@ | tst.js:6:1:6:16 | (req, res) => 42 | ends here | tst.js:6:1:6:16 | (req, res) => 42 | irrelevant |
|
||||
| tst.js:13:1:13:36 | otherAp ... h", rh) | UnpromotedRouteSetupPoI | tst.js:13:1:13:36 | otherAp ... h", rh) | irrelevant | tst.js:13:1:13:36 | otherAp ... h", rh) | irrelevant |
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @kind problem
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import experimental.poi.PoI
|
||||
|
||||
class MyServerRelatedPoIs extends ServerRelatedPoI, ActivePoI { }
|
||||
|
||||
query predicate problems = alertQuery/6;
|
||||
3
javascript/ql/test/experimental/PoI/ServerPoIs.expected
Normal file
3
javascript/ql/test/experimental/PoI/ServerPoIs.expected
Normal file
@@ -0,0 +1,3 @@
|
||||
| tst.js:6:1:6:16 | (req, res) => 42 | UnpromotedRouteHandlerPoI | tst.js:6:1:6:16 | (req, res) => 42 | irrelevant | tst.js:6:1:6:16 | (req, res) => 42 | irrelevant |
|
||||
| tst.js:6:1:6:16 | (req, res) => 42 | UnpromotedRouteHandlerWithFlowPoI: $@ | tst.js:6:1:6:16 | (req, res) => 42 | ends here | tst.js:6:1:6:16 | (req, res) => 42 | irrelevant |
|
||||
| tst.js:13:1:13:36 | otherAp ... h", rh) | UnpromotedRouteSetupPoI | tst.js:13:1:13:36 | otherAp ... h", rh) | irrelevant | tst.js:13:1:13:36 | otherAp ... h", rh) | irrelevant |
|
||||
10
javascript/ql/test/experimental/PoI/ServerPoIs.ql
Normal file
10
javascript/ql/test/experimental/PoI/ServerPoIs.ql
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @kind problem
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import experimental.poi.PoI
|
||||
|
||||
class MyServerRelatedPoI extends ServerRelatedPoI, ActivePoI { }
|
||||
|
||||
query predicate problems = alertQuery/6;
|
||||
@@ -0,0 +1,6 @@
|
||||
| tst.js:1:23:1:31 | "express" | SinkPoI | tst.js:1:23:1:31 | "express" | irrelevant | tst.js:1:23:1:31 | "express" | irrelevant |
|
||||
| tst.js:2:16:2:19 | "fs" | SinkPoI | tst.js:2:16:2:19 | "fs" | irrelevant | tst.js:2:16:2:19 | "fs" | irrelevant |
|
||||
| tst.js:3:16:3:30 | "child_process" | SinkPoI | tst.js:3:16:3:30 | "child_process" | irrelevant | tst.js:3:16:3:30 | "child_process" | irrelevant |
|
||||
| tst.js:16:15:16:25 | req.query.x | SourcePoI | tst.js:16:15:16:25 | req.query.x | irrelevant | tst.js:16:15:16:25 | req.query.x | irrelevant |
|
||||
| tst.js:17:11:17:21 | req.query.x | SourcePoI | tst.js:17:11:17:21 | req.query.x | irrelevant | tst.js:17:11:17:21 | req.query.x | irrelevant |
|
||||
| tst.js:18:12:18:22 | req.query.x | SourcePoI | tst.js:18:12:18:22 | req.query.x | irrelevant | tst.js:18:12:18:22 | req.query.x | irrelevant |
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* @kind problem
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import experimental.poi.PoI
|
||||
import semmle.javascript.security.dataflow.TaintedPath
|
||||
|
||||
class MyDataflowRelatedPoIs extends DataFlowConfigurationPoI, ActivePoI { }
|
||||
|
||||
query predicate problems = alertQuery/6;
|
||||
@@ -0,0 +1,9 @@
|
||||
| tst.js:8:1:8:44 | app.get ... es) {}) | RouteSetupAndRouterAndRouteHandlerPoI: $@ $@ | tst.js:4:11:4:19 | express() | router | tst.js:8:23:8:43 | functio ... res) {} | routehandler |
|
||||
| tst.js:8:23:8:43 | functio ... res) {} | RouteHandlerAndSetupPoI: $@ | tst.js:8:1:8:44 | app.get ... es) {}) | setup | tst.js:8:23:8:43 | functio ... res) {} | irrelevant |
|
||||
| tst.js:8:23:8:43 | functio ... res) {} | RouteHandlerPoI | tst.js:8:23:8:43 | functio ... res) {} | irrelevant | tst.js:8:23:8:43 | functio ... res) {} | irrelevant |
|
||||
| tst.js:10:10:10:30 | functio ... res) {} | RouteHandlerAndSetupPoI: $@ | tst.js:11:1:11:31 | app.get ... h", rh) | setup | tst.js:10:10:10:30 | functio ... res) {} | irrelevant |
|
||||
| tst.js:10:10:10:30 | functio ... res) {} | RouteHandlerPoI | tst.js:10:10:10:30 | functio ... res) {} | irrelevant | tst.js:10:10:10:30 | functio ... res) {} | irrelevant |
|
||||
| tst.js:11:1:11:31 | app.get ... h", rh) | RouteSetupAndRouterAndRouteHandlerPoI: $@ $@ | tst.js:4:11:4:19 | express() | router | tst.js:10:10:10:30 | functio ... res) {} | routehandler |
|
||||
| tst.js:15:1:19:2 | app.get ... .x);\\n}) | RouteSetupAndRouterAndRouteHandlerPoI: $@ $@ | tst.js:4:11:4:19 | express() | router | tst.js:15:23:19:1 | functio ... y.x);\\n} | routehandler |
|
||||
| tst.js:15:23:19:1 | functio ... y.x);\\n} | RouteHandlerAndSetupPoI: $@ | tst.js:15:1:19:2 | app.get ... .x);\\n}) | setup | tst.js:15:23:19:1 | functio ... y.x);\\n} | irrelevant |
|
||||
| tst.js:15:23:19:1 | functio ... y.x);\\n} | RouteHandlerPoI | tst.js:15:23:19:1 | functio ... y.x);\\n} | irrelevant | tst.js:15:23:19:1 | functio ... y.x);\\n} | irrelevant |
|
||||
34
javascript/ql/test/experimental/PoI/TestCustomPoIs.ql
Normal file
34
javascript/ql/test/experimental/PoI/TestCustomPoIs.ql
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @kind problem
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import experimental.poi.PoI
|
||||
import DataFlow
|
||||
|
||||
class RouteHandlerPoI extends ActivePoI {
|
||||
RouteHandlerPoI() { this = "RouteHandlerPoI" }
|
||||
|
||||
override predicate is(Node l0) { l0 instanceof Express::RouteHandler }
|
||||
}
|
||||
|
||||
class RouteHandlerAndSetupPoI extends ActivePoI {
|
||||
RouteHandlerAndSetupPoI() { this = "RouteHandlerAndSetupPoI" }
|
||||
|
||||
override predicate is(Node l0, Node l1, string t1) {
|
||||
l1.asExpr().(Express::RouteSetup).getARouteHandler() = l0 and t1 = "setup"
|
||||
}
|
||||
}
|
||||
|
||||
class RouteSetupAndRouterAndRouteHandlerPoI extends ActivePoI {
|
||||
RouteSetupAndRouterAndRouteHandlerPoI() { this = "RouteSetupAndRouterAndRouteHandlerPoI" }
|
||||
|
||||
override predicate is(Node l0, Node l1, string t1, Node l2, string t2) {
|
||||
l0.asExpr().(Express::RouteSetup).getRouter().flow() = l1 and
|
||||
t1 = "router" and
|
||||
l0.asExpr().(Express::RouteSetup).getARouteHandler() = l2 and
|
||||
t2 = "routehandler"
|
||||
}
|
||||
}
|
||||
|
||||
query predicate problems = alertQuery/6;
|
||||
@@ -0,0 +1 @@
|
||||
| tst.js:6:1:6:16 | (req, res) => 42 | UnpromotedRouteHandlerPoI | tst.js:6:1:6:16 | (req, res) => 42 | irrelevant | tst.js:6:1:6:16 | (req, res) => 42 | irrelevant |
|
||||
10
javascript/ql/test/experimental/PoI/TestStandardPoIs.ql
Normal file
10
javascript/ql/test/experimental/PoI/TestStandardPoIs.ql
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @kind problem
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import experimental.poi.PoI
|
||||
|
||||
class MyUnpromotedRouteHandlerPoIs extends UnpromotedRouteHandlerPoI, ActivePoI { }
|
||||
|
||||
query predicate problems = alertQuery/6;
|
||||
@@ -0,0 +1,4 @@
|
||||
| tst.js:16:15:16:25 | req.query.x | SourcePoI | tst.js:16:15:16:25 | req.query.x | irrelevant | tst.js:16:15:16:25 | req.query.x | irrelevant |
|
||||
| tst.js:17:11:17:21 | req.query.x | SourcePoI | tst.js:17:11:17:21 | req.query.x | irrelevant | tst.js:17:11:17:21 | req.query.x | irrelevant |
|
||||
| tst.js:18:12:18:22 | req.query.x | SinkPoI | tst.js:18:12:18:22 | req.query.x | irrelevant | tst.js:18:12:18:22 | req.query.x | irrelevant |
|
||||
| tst.js:18:12:18:22 | req.query.x | SourcePoI | tst.js:18:12:18:22 | req.query.x | irrelevant | tst.js:18:12:18:22 | req.query.x | irrelevant |
|
||||
14
javascript/ql/test/experimental/PoI/XssPoIConfiguration.ql
Normal file
14
javascript/ql/test/experimental/PoI/XssPoIConfiguration.ql
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @kind problem
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import experimental.poi.PoI
|
||||
import semmle.javascript.security.dataflow.ReflectedXss
|
||||
import semmle.javascript.security.dataflow.StoredXss
|
||||
import semmle.javascript.security.dataflow.DomBasedXss
|
||||
import semmle.javascript.security.dataflow.ExceptionXss
|
||||
|
||||
class MyDataFlowConfigurationPoIs extends DataFlowConfigurationPoI, ActivePoI { }
|
||||
|
||||
query predicate problems = alertQuery/6;
|
||||
19
javascript/ql/test/experimental/PoI/tst.js
Normal file
19
javascript/ql/test/experimental/PoI/tst.js
Normal file
@@ -0,0 +1,19 @@
|
||||
var express = require("express"),
|
||||
fs = require("fs"),
|
||||
cp = require("child_process");
|
||||
var app = express();
|
||||
|
||||
(req, res) => 42;
|
||||
|
||||
app.get("/some/path", function(req, res) {});
|
||||
|
||||
let rh = function(req, res) {};
|
||||
app.get("/some/other/path", rh);
|
||||
|
||||
otherApp.get("/some/other/path", rh);
|
||||
|
||||
app.get("/some/path", function(req, res) {
|
||||
fs.readFile(req.query.x);
|
||||
cp.exec(req.query.x);
|
||||
res.send(req.query.x);
|
||||
});
|
||||
@@ -341,6 +341,12 @@ nodes
|
||||
| tst.js:347:20:347:36 | document.location |
|
||||
| tst.js:349:5:349:30 | getUrl( ... ring(1) |
|
||||
| tst.js:349:5:349:30 | getUrl( ... ring(1) |
|
||||
| tst.js:354:7:354:39 | target |
|
||||
| tst.js:354:16:354:32 | document.location |
|
||||
| tst.js:354:16:354:32 | document.location |
|
||||
| tst.js:354:16:354:39 | documen ... .search |
|
||||
| tst.js:355:12:355:17 | target |
|
||||
| tst.js:355:12:355:17 | target |
|
||||
| typeahead.js:20:13:20:45 | target |
|
||||
| typeahead.js:20:22:20:38 | document.location |
|
||||
| typeahead.js:20:22:20:38 | document.location |
|
||||
@@ -659,6 +665,11 @@ edges
|
||||
| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) |
|
||||
| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) |
|
||||
| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) |
|
||||
| tst.js:354:7:354:39 | target | tst.js:355:12:355:17 | target |
|
||||
| tst.js:354:7:354:39 | target | tst.js:355:12:355:17 | target |
|
||||
| tst.js:354:16:354:32 | document.location | tst.js:354:16:354:39 | documen ... .search |
|
||||
| tst.js:354:16:354:32 | document.location | tst.js:354:16:354:39 | documen ... .search |
|
||||
| tst.js:354:16:354:39 | documen ... .search | tst.js:354:7:354:39 | target |
|
||||
| typeahead.js:20:13:20:45 | target | typeahead.js:21:12:21:17 | target |
|
||||
| typeahead.js:20:22:20:38 | document.location | typeahead.js:20:22:20:45 | documen ... .search |
|
||||
| typeahead.js:20:22:20:38 | document.location | typeahead.js:20:22:20:45 | documen ... .search |
|
||||
@@ -760,6 +771,7 @@ edges
|
||||
| tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | Cross-site scripting vulnerability due to $@. | tst.js:319:35:319:42 | location | user-provided value |
|
||||
| tst.js:336:18:336:35 | params.get('name') | tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | Cross-site scripting vulnerability due to $@. | tst.js:330:18:330:34 | document.location | user-provided value |
|
||||
| tst.js:349:5:349:30 | getUrl( ... ring(1) | tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | Cross-site scripting vulnerability due to $@. | tst.js:347:20:347:36 | document.location | user-provided value |
|
||||
| tst.js:355:12:355:17 | target | tst.js:354:16:354:32 | document.location | tst.js:355:12:355:17 | target | Cross-site scripting vulnerability due to $@. | tst.js:354:16:354:32 | document.location | user-provided value |
|
||||
| typeahead.js:25:18:25:20 | val | typeahead.js:20:22:20:38 | document.location | typeahead.js:25:18:25:20 | val | Cross-site scripting vulnerability due to $@. | typeahead.js:20:22:20:38 | document.location | user-provided value |
|
||||
| v-html.vue:2:8:2:23 | v-html=tainted | v-html.vue:6:42:6:58 | document.location | v-html.vue:2:8:2:23 | v-html=tainted | Cross-site scripting vulnerability due to $@. | v-html.vue:6:42:6:58 | document.location | user-provided value |
|
||||
| winjs.js:3:43:3:49 | tainted | winjs.js:2:17:2:33 | document.location | winjs.js:3:43:3:49 | tainted | Cross-site scripting vulnerability due to $@. | winjs.js:2:17:2:33 | document.location | user-provided value |
|
||||
|
||||
@@ -38,6 +38,9 @@ nodes
|
||||
| xss-through-dom.js:64:30:64:40 | valMethod() |
|
||||
| xss-through-dom.js:64:30:64:40 | valMethod() |
|
||||
| xss-through-dom.js:64:30:64:40 | valMethod() |
|
||||
| xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name |
|
||||
| xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name |
|
||||
| xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name |
|
||||
edges
|
||||
| xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() |
|
||||
| xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() |
|
||||
@@ -52,6 +55,7 @@ edges
|
||||
| xss-through-dom.js:57:30:57:67 | $("inpu ... "name") | xss-through-dom.js:57:30:57:67 | $("inpu ... "name") |
|
||||
| xss-through-dom.js:61:30:61:69 | $(docum ... value") | xss-through-dom.js:61:30:61:69 | $(docum ... value") |
|
||||
| xss-through-dom.js:64:30:64:40 | valMethod() | xss-through-dom.js:64:30:64:40 | valMethod() |
|
||||
| xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name | xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name |
|
||||
#select
|
||||
| xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | Cross-site scripting vulnerability due to $@. | xss-through-dom.js:2:16:2:34 | $("textarea").val() | DOM text |
|
||||
| xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | Cross-site scripting vulnerability due to $@. | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | DOM text |
|
||||
@@ -66,3 +70,4 @@ edges
|
||||
| xss-through-dom.js:57:30:57:67 | $("inpu ... "name") | xss-through-dom.js:57:30:57:67 | $("inpu ... "name") | xss-through-dom.js:57:30:57:67 | $("inpu ... "name") | Cross-site scripting vulnerability due to $@. | xss-through-dom.js:57:30:57:67 | $("inpu ... "name") | DOM text |
|
||||
| xss-through-dom.js:61:30:61:69 | $(docum ... value") | xss-through-dom.js:61:30:61:69 | $(docum ... value") | xss-through-dom.js:61:30:61:69 | $(docum ... value") | Cross-site scripting vulnerability due to $@. | xss-through-dom.js:61:30:61:69 | $(docum ... value") | DOM text |
|
||||
| xss-through-dom.js:64:30:64:40 | valMethod() | xss-through-dom.js:64:30:64:40 | valMethod() | xss-through-dom.js:64:30:64:40 | valMethod() | Cross-site scripting vulnerability due to $@. | xss-through-dom.js:64:30:64:40 | valMethod() | DOM text |
|
||||
| xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name | xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name | xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name | Cross-site scripting vulnerability due to $@. | xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name | DOM text |
|
||||
|
||||
@@ -341,6 +341,12 @@ nodes
|
||||
| tst.js:347:20:347:36 | document.location |
|
||||
| tst.js:349:5:349:30 | getUrl( ... ring(1) |
|
||||
| tst.js:349:5:349:30 | getUrl( ... ring(1) |
|
||||
| tst.js:354:7:354:39 | target |
|
||||
| tst.js:354:16:354:32 | document.location |
|
||||
| tst.js:354:16:354:32 | document.location |
|
||||
| tst.js:354:16:354:39 | documen ... .search |
|
||||
| tst.js:355:12:355:17 | target |
|
||||
| tst.js:355:12:355:17 | target |
|
||||
| typeahead.js:9:28:9:30 | loc |
|
||||
| typeahead.js:9:28:9:30 | loc |
|
||||
| typeahead.js:10:16:10:18 | loc |
|
||||
@@ -663,6 +669,11 @@ edges
|
||||
| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) |
|
||||
| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) |
|
||||
| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) |
|
||||
| tst.js:354:7:354:39 | target | tst.js:355:12:355:17 | target |
|
||||
| tst.js:354:7:354:39 | target | tst.js:355:12:355:17 | target |
|
||||
| tst.js:354:16:354:32 | document.location | tst.js:354:16:354:39 | documen ... .search |
|
||||
| tst.js:354:16:354:32 | document.location | tst.js:354:16:354:39 | documen ... .search |
|
||||
| tst.js:354:16:354:39 | documen ... .search | tst.js:354:7:354:39 | target |
|
||||
| typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc |
|
||||
| typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc |
|
||||
| typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc |
|
||||
|
||||
@@ -348,4 +348,10 @@ function hash() {
|
||||
}
|
||||
$(getUrl().hash.substring(1)); // NOT OK
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function growl() {
|
||||
var target = document.location.search
|
||||
$.jGrowl(target); // NOT OK
|
||||
}
|
||||
|
||||
|
||||
@@ -67,4 +67,6 @@
|
||||
if(myValue.property) {
|
||||
$("#id").get(0).innerHTML = myValue; // OK.
|
||||
}
|
||||
|
||||
$.jGrowl($("input").get(0).name); // NOT OK.
|
||||
})();
|
||||
@@ -1,10 +1,10 @@
|
||||
import python
|
||||
|
||||
from NameNode name, CallNode call, string debug
|
||||
from ControlFlowNode arg, CallNode call, string debug
|
||||
where
|
||||
call.getAnArg() = name and
|
||||
call.getAnArg() = arg and
|
||||
call.getFunction().(NameNode).getId() = "check" and
|
||||
if exists(name.pointsTo())
|
||||
then debug = name.pointsTo().toString()
|
||||
if exists(arg.pointsTo())
|
||||
then debug = arg.pointsTo().toString()
|
||||
else debug = "<MISSING pointsTo()>"
|
||||
select name, debug
|
||||
select arg, debug
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import python
|
||||
|
||||
from NameNode name, CallNode call, string debug
|
||||
from ControlFlowNode arg, CallNode call, string debug
|
||||
where
|
||||
call.getAnArg() = name and
|
||||
call.getAnArg() = arg and
|
||||
call.getFunction().(NameNode).getId() = "check" and
|
||||
if exists(name.pointsTo())
|
||||
then debug = name.pointsTo().toString()
|
||||
if exists(arg.pointsTo())
|
||||
then debug = arg.pointsTo().toString()
|
||||
else debug = "<MISSING pointsTo()>"
|
||||
select name, debug
|
||||
select arg, debug
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
| test.py:10:11:10:14 | ControlFlowNode for open | <MISSING pointsTo()> |
|
||||
| test.py:14:11:14:14 | ControlFlowNode for open | Builtin-function open |
|
||||
@@ -0,0 +1,10 @@
|
||||
import python
|
||||
|
||||
from ControlFlowNode arg, CallNode call, string debug
|
||||
where
|
||||
call.getAnArg() = arg and
|
||||
call.getFunction().(NameNode).getId() = "check" and
|
||||
if exists(arg.pointsTo())
|
||||
then debug = arg.pointsTo().toString()
|
||||
else debug = "<MISSING pointsTo()>"
|
||||
select arg, debug
|
||||
@@ -0,0 +1,18 @@
|
||||
# Points-to information seems to be missing if our analysis thinks the enclosing function
|
||||
# is never called. However, as illustrated by the code below, it's easy to fool our
|
||||
# analysis :(
|
||||
|
||||
# This was inspired by a problem in real code, where our analysis doesn't have any
|
||||
# points-to information about the `open` call in
|
||||
# https://google-gruyere.appspot.com/code/gruyere.py on line 227
|
||||
|
||||
def _func_not_called(filename, mode='rb'):
|
||||
check(open)
|
||||
return open(filename, mode)
|
||||
|
||||
def _func_called(filename, mode='rb'):
|
||||
check(open)
|
||||
return open(filename, mode)
|
||||
|
||||
globals()['_func_not_called']('test.txt')
|
||||
_func_called('test.txt')
|
||||
Reference in New Issue
Block a user