Merge branch 'main' into 20823-globalVarRef-document-defaultView

This commit is contained in:
Eliav2
2025-11-26 23:26:26 +02:00
committed by GitHub
212 changed files with 16554 additions and 3130 deletions

View File

@@ -1,5 +1,5 @@
/**
* @name Artifact Poisoning (Path Traversal).
* @name Artifact Poisoning (Path Traversal)
* @description An attacker may be able to poison the workflow's artifacts and influence on consequent steps.
* @kind problem
* @problem.severity error

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
description: Add databaseMetadata and overlayChangedFiles relations
compatibility: full
databaseMetadata.rel: delete
overlayChangedFiles.rel: delete

View File

@@ -21,3 +21,4 @@ dataExtensions:
- ext/deallocation/*.model.yml
- ext/allocation/*.model.yml
warnOnImplicitThis: true
compileForOverlayEval: true

View File

@@ -15,16 +15,17 @@
* reading.
* 1. The `namespace` column selects a namespace.
* 2. The `type` column selects a type within that namespace. This column can
* introduce template names that can be mentioned in the `signature` column.
* introduce template type names that can be mentioned in the `signature` column.
* For example, `vector<T,Allocator>` introduces the template names `T` and
* `Allocator`.
* `Allocator`. Non-type template parameters cannot be specified.
* 3. The `subtypes` is a boolean that indicates whether to jump to an
* arbitrary subtype of that type. Set this to `false` if leaving the `type`
* blank (for example, a free function).
* 4. The `name` column optionally selects a specific named member of the type.
* Like the `type` column, this column can introduce template names that can
* be mentioned in the `signature` column. For example, `insert<InputIt>`
* introduces the template name `InputIt`.
* Like the `type` column, this column can introduce template type names
* that can be mentioned in the `signature` column. For example,
* `insert<InputIt>` introduces the template name `InputIt`. Non-type
* template parameters cannot be specified.
* 5. The `signature` column optionally restricts the named member. If
* `signature` is blank then no such filtering is done. The format of the
* signature is a comma-separated list of types enclosed in parentheses. The
@@ -633,6 +634,28 @@ string getParameterTypeWithoutTemplateArguments(Function f, int n, boolean canon
canonical = true
}
/**
* Gets the largest index of a template parameter of `templateFunction` that
* is a type template parameter.
*/
private int getLastTypeTemplateFunctionParameterIndex(Function templateFunction) {
result =
max(int index | templateFunction.getTemplateArgument(index) instanceof TypeTemplateParameter)
}
/** Gets the number of supported template parameters for `templateFunction`. */
private int getNumberOfSupportedFunctionTemplateArguments(Function templateFunction) {
result = count(int i | exists(getSupportedFunctionTemplateArgument(templateFunction, i)) | i)
}
/** Gets the `i`'th supported template parameter for `templateFunction`. */
private Locatable getSupportedFunctionTemplateArgument(Function templateFunction, int i) {
result = templateFunction.getTemplateArgument(i) and
// We don't yet support non-type template parameters in the middle of a
// template parameter list
i <= getLastTypeTemplateFunctionParameterIndex(templateFunction)
}
/**
* Normalize the `n`'th parameter of `f` by replacing template names
* with `func:N` (where `N` is the index of the template).
@@ -640,18 +663,41 @@ string getParameterTypeWithoutTemplateArguments(Function f, int n, boolean canon
private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) {
exists(Function templateFunction |
templateFunction = getFullyTemplatedFunction(f) and
remaining = templateFunction.getNumberOfTemplateArguments() and
remaining = getNumberOfSupportedFunctionTemplateArguments(templateFunction) and
result = getParameterTypeWithoutTemplateArguments(templateFunction, n, _)
)
or
exists(string mid, TypeTemplateParameter tp, Function templateFunction |
mid = getTypeNameWithoutFunctionTemplates(f, n, remaining + 1) and
templateFunction = getFullyTemplatedFunction(f) and
tp = templateFunction.getTemplateArgument(remaining) and
tp = getSupportedFunctionTemplateArgument(templateFunction, remaining)
|
result = mid.replaceAll(tp.getName(), "func:" + remaining.toString())
)
}
/**
* Gets the largest index of a template parameter of `templateClass` that
* is a type template parameter.
*/
private int getLastTypeTemplateClassParameterIndex(Class templateClass) {
result =
max(int index | templateClass.getTemplateArgument(index) instanceof TypeTemplateParameter)
}
/** Gets the `i`'th supported template parameter for `templateClass`. */
private Locatable getSupportedClassTemplateArgument(Class templateClass, int i) {
result = templateClass.getTemplateArgument(i) and
// We don't yet support non-type template parameters in the middle of a
// template parameter list
i <= getLastTypeTemplateClassParameterIndex(templateClass)
}
/** Gets the number of supported template parameters for `templateClass`. */
private int getNumberOfSupportedClassTemplateArguments(Class templateClass) {
result = count(int i | exists(getSupportedClassTemplateArgument(templateClass, i)) | i)
}
/**
* Normalize the `n`'th parameter of `f` by replacing template names
* with `class:N` (where `N` is the index of the template).
@@ -661,7 +707,7 @@ private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining
// If there is a declaring type then we start by expanding the function templates
exists(Class template |
isClassConstructedFrom(f.getDeclaringType(), template) and
remaining = template.getNumberOfTemplateArguments() and
remaining = getNumberOfSupportedClassTemplateArguments(template) and
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
)
or
@@ -673,7 +719,8 @@ private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining
exists(string mid, TypeTemplateParameter tp, Class template |
mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and
isClassConstructedFrom(f.getDeclaringType(), template) and
tp = template.getTemplateArgument(remaining) and
tp = getSupportedClassTemplateArgument(template, remaining)
|
result = mid.replaceAll(tp.getName(), "class:" + remaining.toString())
)
}

View File

@@ -2078,38 +2078,151 @@ predicate localExprFlow(Expr e1, Expr e2) {
localExprFlowPlus(e1, e2)
}
/**
* A canonical representation of a field.
*
* For performance reasons we want a unique `Content` that represents
* a given field across any template instantiation of a class.
*
* This is possible in _almost_ all cases, but there are cases where it is
* not possible to map between a field in the uninstantiated template to a
* field in the instantiated template. This happens in the case of local class
* definitions (because the local class is not the template that constructs
* the instantiation - it is the enclosing function). So this abstract class
* has two implementations: a non-local case (where we can represent a
* canonical field as the field declaration from an uninstantiated class
* template or a non-templated class), and a local case (where we simply use
* the field from the instantiated class).
*/
abstract private class CanonicalField extends Field {
/** Gets a field represented by this canonical field. */
abstract Field getAField();
/**
* Gets a class that declares a field represented by this canonical field.
*/
abstract Class getADeclaringType();
/**
* Gets a type that this canonical field may have. Note that this may
* not be a unique type. For example, consider this case:
* ```
* template<typename T>
* struct S { T x; };
*
* S<int> s1;
* S<char> s2;
* ```
* In this case the canonical field corresponding to `S::x` has two types:
* `int` and `char`.
*/
Type getAType() { result = this.getAField().getType() }
Type getAnUnspecifiedType() { result = this.getAType().getUnspecifiedType() }
}
private class NonLocalCanonicalField extends CanonicalField {
Class declaringType;
NonLocalCanonicalField() {
declaringType = this.getDeclaringType() and
not declaringType.isFromTemplateInstantiation(_) and
not declaringType.isLocal() // handled in LocalCanonicalField
}
override Field getAField() {
exists(Class c | result.getDeclaringType() = c |
// Either the declaring class of the field is a template instantiation
// that has been constructed from this canonical declaration
c.isConstructedFrom(declaringType) and
pragma[only_bind_out](result.getName()) = pragma[only_bind_out](this.getName())
or
// or this canonical declaration is not a template.
not c.isConstructedFrom(_) and
result = this
)
}
override Class getADeclaringType() {
result = this.getDeclaringType()
or
result.isConstructedFrom(this.getDeclaringType())
}
}
private class LocalCanonicalField extends CanonicalField {
Class declaringType;
LocalCanonicalField() {
declaringType = this.getDeclaringType() and
declaringType.isLocal()
}
override Field getAField() { result = this }
override Class getADeclaringType() { result = declaringType }
}
/**
* A canonical representation of a `Union`. See `CanonicalField` for the explanation for
* why we need a canonical representation.
*/
abstract private class CanonicalUnion extends Union {
/** Gets a union represented by this canonical union. */
abstract Union getAUnion();
/** Gets a canonical field of this canonical union. */
CanonicalField getACanonicalField() { result.getDeclaringType() = this }
}
private class NonLocalCanonicalUnion extends CanonicalUnion {
NonLocalCanonicalUnion() { not this.isFromTemplateInstantiation(_) and not this.isLocal() }
override Union getAUnion() {
result = this
or
result.isConstructedFrom(this)
}
}
private class LocalCanonicalUnion extends CanonicalUnion {
LocalCanonicalUnion() { this.isLocal() }
override Union getAUnion() { result = this }
}
bindingset[f]
pragma[inline_late]
private int getFieldSize(Field f) { result = f.getType().getSize() }
private int getFieldSize(CanonicalField f) { result = max(f.getAType().getSize()) }
/**
* Gets a field in the union `u` whose size
* is `bytes` number of bytes.
*/
private Field getAFieldWithSize(Union u, int bytes) {
result = u.getAField() and
private CanonicalField getAFieldWithSize(CanonicalUnion u, int bytes) {
result = u.getACanonicalField() and
bytes = getFieldSize(result)
}
cached
private newtype TContent =
TNonUnionContent(Field f, int indirectionIndex) {
TNonUnionContent(CanonicalField f, int indirectionIndex) {
// the indirection index for field content starts at 1 (because `TNonUnionContent` is thought of as
// the address of the field, `FieldAddress` in the IR).
indirectionIndex = [1 .. SsaImpl::getMaxIndirectionsForType(f.getUnspecifiedType())] and
indirectionIndex = [1 .. max(SsaImpl::getMaxIndirectionsForType(f.getAnUnspecifiedType()))] and
// Reads and writes of union fields are tracked using `UnionContent`.
not f.getDeclaringType() instanceof Union
} or
TUnionContent(Union u, int bytes, int indirectionIndex) {
exists(Field f |
f = u.getAField() and
TUnionContent(CanonicalUnion u, int bytes, int indirectionIndex) {
exists(CanonicalField f |
f = u.getACanonicalField() and
bytes = getFieldSize(f) and
// We key `UnionContent` by the union instead of its fields since a write to one
// field can be read by any read of the union's fields. Again, the indirection index
// is 1-based (because 0 is considered the address).
indirectionIndex =
[1 .. max(SsaImpl::getMaxIndirectionsForType(getAFieldWithSize(u, bytes)
.getUnspecifiedType())
.getAnUnspecifiedType())
)]
)
} or
@@ -2175,8 +2288,12 @@ class FieldContent extends Content, TFieldContent {
/**
* Gets the field associated with this `Content`, if a unique one exists.
*
* For fields from template instantiations this predicate may still return
* more than one field, but all the fields will be constructed from the same
* template.
*/
final Field getField() { result = unique( | | this.getAField()) }
Field getField() { none() } // overridden in subclasses
override int getIndirectionIndex() { none() } // overridden in subclasses
@@ -2187,32 +2304,33 @@ class FieldContent extends Content, TFieldContent {
/** A reference through a non-union instance field. */
class NonUnionFieldContent extends FieldContent, TNonUnionContent {
private Field f;
private CanonicalField f;
private int indirectionIndex;
NonUnionFieldContent() { this = TNonUnionContent(f, indirectionIndex) }
override string toString() { result = contentStars(this) + f.toString() }
override Field getAField() { result = f }
final override Field getField() { result = f.getAField() }
override Field getAField() { result = this.getField() }
/** Gets the indirection index of this `FieldContent`. */
override int getIndirectionIndex() { result = indirectionIndex }
override predicate impliesClearOf(Content c) {
exists(FieldContent fc |
fc = c and
fc.getField() = f and
exists(int i |
c = TNonUnionContent(f, i) and
// If `this` is `f` then `c` is cleared if it's of the
// form `*f`, `**f`, etc.
fc.getIndirectionIndex() >= indirectionIndex
i >= indirectionIndex
)
}
}
/** A reference through an instance field of a union. */
class UnionContent extends FieldContent, TUnionContent {
private Union u;
private CanonicalUnion u;
private int indirectionIndex;
private int bytes;
@@ -2220,24 +2338,31 @@ class UnionContent extends FieldContent, TUnionContent {
override string toString() { result = contentStars(this) + u.toString() }
final override Field getField() { result = unique( | | u.getACanonicalField()).getAField() }
/** Gets a field of the underlying union of this `UnionContent`, if any. */
override Field getAField() { result = u.getAField() and getFieldSize(result) = bytes }
override Field getAField() {
exists(CanonicalField cf |
cf = u.getACanonicalField() and
result = cf.getAField() and
getFieldSize(cf) = bytes
)
}
/** Gets the underlying union of this `UnionContent`. */
Union getUnion() { result = u }
Union getUnion() { result = u.getAUnion() }
/** Gets the indirection index of this `UnionContent`. */
override int getIndirectionIndex() { result = indirectionIndex }
override predicate impliesClearOf(Content c) {
exists(UnionContent uc |
uc = c and
uc.getUnion() = u and
exists(int i |
c = TUnionContent(u, _, i) and
// If `this` is `u` then `c` is cleared if it's of the
// form `*u`, `**u`, etc. (and we ignore `bytes` because
// we know the entire union is overwritten because it's a
// union).
uc.getIndirectionIndex() >= indirectionIndex
i >= indirectionIndex
)
}
}

View File

@@ -1,3 +1,4 @@
/*- Compilations -*/
/**
@@ -2378,6 +2379,24 @@ link_parent(
int link_target : @link_target ref
);
/**
* The CLI will automatically emit applicable tuples for this table,
* such as `databaseMetadata("isOverlay", "true")` when building an
* overlay database.
*/
databaseMetadata(
string metadataKey: string ref,
string value: string ref
);
/**
* The CLI will automatically emit tuples for each new/modified/deleted file
* when building an overlay database.
*/
overlayChangedFiles(
string path: string ref
);
/*- XML Files -*/
xmlEncoding(

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Add databaseMetadata and overlayChangedFiles relations
compatibility: full

View File

@@ -1,5 +1,5 @@
/**
* @name Dangerous use convert function.
* @name Dangerous use convert function
* @description Using convert function with an invalid length argument can result in an out-of-bounds access error or unexpected result.
* @kind problem
* @id cpp/dangerous-use-convert-function

View File

@@ -1,5 +1,5 @@
/**
* @name Dangerous use of transformation after operation.
* @name Dangerous use of transformation after operation
* @description By using the transformation after the operation, you are doing a pointless and dangerous action.
* @kind problem
* @id cpp/dangerous-use-of-transformation-after-operation

View File

@@ -1,5 +1,5 @@
/**
* @name Writing to a file without setting permissions.
* @name Writing to a file without setting permissions
* @description Lack of restriction on file access rights can be unsafe.
* @kind problem
* @id cpp/work-with-file-without-permissions-rights

View File

@@ -1,5 +1,5 @@
/**
* @name Find work with changing working directories, with security errors.
* @name Find work with changing working directories, with security errors
* @description Not validating the return value or pinning the directory can be unsafe.
* @kind problem
* @id cpp/work-with-changing-working-directories

View File

@@ -1,5 +1,5 @@
/**
* @name Find the wrong use of the umask function.
* @name Find the wrong use of the umask function
* @description Incorrectly evaluated argument to the umask function may have security implications.
* @kind problem
* @id cpp/wrong-use-of-the-umask

View File

@@ -1,5 +1,5 @@
/**
* @name Insecure generation of filenames.
* @name Insecure generation of filenames
* @description Using a predictable filename when creating a temporary file can lead to an attacker-controlled input.
* @kind problem
* @id cpp/insecure-generation-of-filename

View File

@@ -1,5 +1,5 @@
/**
* @name Dangerous use of exception blocks.
* @name Dangerous use of exception blocks
* @description When clearing the data in the catch block, you must be sure that the memory was allocated before the exception.
* @kind problem
* @id cpp/dangerous-use-of-exception-blocks

View File

@@ -1,5 +1,5 @@
/**
* @name Dangerous use SSL_shutdown.
* @name Dangerous use SSL_shutdown
* @description Incorrect closing of the connection leads to the creation of different states for the server and client, which can be exploited by an attacker.
* @kind problem
* @id cpp/dangerous-use-of-ssl-shutdown

View File

@@ -1,5 +1,5 @@
/**
* @name Capture content based summary models.
* @name Capture content based summary models
* @description Finds applicable content based summary models to be used by other queries.
* @kind diagnostic
* @id cpp/utils/modelgenerator/contentbased-summary-models

View File

@@ -1,5 +1,5 @@
/**
* @name Capture neutral models.
* @name Capture neutral models
* @description Finds neutral models to be used by other queries.
* @kind diagnostic
* @id cpp/utils/modelgenerator/neutral-models

View File

@@ -1,5 +1,5 @@
/**
* @name Capture sink models.
* @name Capture sink models
* @description Finds public methods that act as sinks as they flow into a known sink.
* @kind diagnostic
* @id cpp/utils/modelgenerator/sink-models

View File

@@ -1,5 +1,5 @@
/**
* @name Capture source models.
* @name Capture source models
* @description Finds APIs that act as sources as they expose already known sources.
* @kind diagnostic
* @id cpp/utils/modelgenerator/source-models

View File

@@ -1,5 +1,5 @@
/**
* @name Capture summary models.
* @name Capture summary models
* @description Finds applicable summary models to be used by other queries.
* @kind diagnostic
* @id cpp/utils/modelgenerator/summary-models

View File

@@ -1,4 +1,2 @@
| clang421.c:1:12:1:19 | clang421 | 0 |
| clang450.c:1:12:1:19 | clang450 | 1 |
| gcc421.c:1:12:1:17 | gcc421 | 0 |
| gcc450.c:1:12:1:17 | gcc450 | 1 |

View File

@@ -1,2 +0,0 @@
static int gcc421 = __has_feature(attribute_deprecated_with_message);
// semmle-extractor-options: --gnu_version 40201

View File

@@ -1,2 +0,0 @@
static int gcc450 = __has_feature(attribute_deprecated_with_message);
// semmle-extractor-options: --gnu_version 40500

View File

@@ -30,13 +30,14 @@ models
| 29 | Summary: ; ; false; RtlMoveMemory; ; ; Argument[*@1]; Argument[*@0]; value; manual |
| 30 | Summary: ; ; false; RtlMoveVolatileMemory; ; ; Argument[*@1]; Argument[*@0]; value; manual |
| 31 | Summary: ; ; false; callWithArgument; ; ; Argument[1]; Argument[0].Parameter[0]; value; manual |
| 32 | Summary: ; ; false; pthread_create; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual |
| 33 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
| 34 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
| 35 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
| 36 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
| 32 | Summary: ; ; false; callWithNonTypeTemplate<T>; (const T &); ; Argument[*0]; ReturnValue; value; manual |
| 33 | Summary: ; ; false; pthread_create; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual |
| 34 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
| 35 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
| 36 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
| 37 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
edges
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:36 |
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:37 |
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:17 |
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:17 Sink:MaD:2 |
| asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction |
@@ -45,10 +46,10 @@ edges
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:36 |
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:34 |
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:33 |
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:35 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:37 |
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:35 |
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:34 |
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:36 |
| test.cpp:7:47:7:52 | value2 | test.cpp:7:64:7:69 | value2 | provenance | |
| test.cpp:7:64:7:69 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | provenance | |
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:16 |
@@ -60,15 +61,15 @@ edges
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | |
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:18:10:18:10 | y | provenance | Sink:MaD:1 |
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | provenance | |
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:34 |
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:35 |
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | |
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:22:10:22:10 | z | provenance | Sink:MaD:1 |
| test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | provenance | |
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:33 |
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:34 |
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | |
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:26:10:26:11 | y2 | provenance | Sink:MaD:1 |
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | provenance | |
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:35 |
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:36 |
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | |
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:33:10:33:11 | z2 | provenance | Sink:MaD:1 |
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | provenance | |
@@ -76,7 +77,7 @@ edges
| test.cpp:46:30:46:32 | *arg [x] | test.cpp:47:12:47:19 | *arg [x] | provenance | |
| test.cpp:47:12:47:19 | *arg [x] | test.cpp:48:13:48:13 | *s [x] | provenance | |
| test.cpp:48:13:48:13 | *s [x] | test.cpp:48:16:48:16 | x | provenance | Sink:MaD:1 |
| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | provenance | MaD:32 |
| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | provenance | MaD:33 |
| test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | test.cpp:46:30:46:32 | *arg [x] | provenance | |
| test.cpp:56:2:56:2 | *s [post update] [x] | test.cpp:59:55:59:64 | *& ... [x] | provenance | |
| test.cpp:56:2:56:18 | ... = ... | test.cpp:56:2:56:2 | *s [post update] [x] | provenance | |
@@ -103,6 +104,13 @@ edges
| test.cpp:101:26:101:26 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
| test.cpp:103:63:103:63 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
| test.cpp:104:62:104:62 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
| test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | provenance | MaD:32 |
| test.cpp:114:10:114:18 | call to ymlSource | test.cpp:114:10:114:18 | call to ymlSource | provenance | Src:MaD:16 |
| test.cpp:114:10:114:18 | call to ymlSource | test.cpp:118:44:118:44 | *x | provenance | |
| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | provenance | |
| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | test.cpp:119:10:119:11 | y2 | provenance | Sink:MaD:1 |
| test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | provenance | |
| test.cpp:118:44:118:44 | *x | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | provenance | MaD:32 |
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | provenance | MaD:18 |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:22:15:22:29 | *call to GetCommandLineA | provenance | Src:MaD:3 |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:24:8:24:11 | * ... | provenance | |
@@ -314,6 +322,14 @@ nodes
| test.cpp:101:26:101:26 | x | semmle.label | x |
| test.cpp:103:63:103:63 | x | semmle.label | x |
| test.cpp:104:62:104:62 | x | semmle.label | x |
| test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | semmle.label | [summary param] *0 in callWithNonTypeTemplate |
| test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | semmle.label | [summary] to write: ReturnValue in callWithNonTypeTemplate |
| test.cpp:114:10:114:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:114:10:114:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate |
| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate |
| test.cpp:118:44:118:44 | *x | semmle.label | *x |
| test.cpp:119:10:119:11 | y2 | semmle.label | y2 |
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | semmle.label | [summary param] *0 in CommandLineToArgvA |
| windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | semmle.label | [summary] to write: ReturnValue[**] in CommandLineToArgvA |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA |
@@ -472,6 +488,7 @@ subpaths
| test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated |
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body |
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body |
| test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate |
| windows.cpp:27:36:27:38 | *cmd | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | windows.cpp:27:17:27:34 | **call to CommandLineToArgvA |
| windows.cpp:537:40:537:41 | *& ... | windows.cpp:473:17:473:37 | [summary param] *1 in RtlCopyVolatileMemory | windows.cpp:473:17:473:37 | [summary param] *0 in RtlCopyVolatileMemory [Return] | windows.cpp:537:27:537:37 | RtlCopyVolatileMemory output argument |
| windows.cpp:542:38:542:39 | *& ... | windows.cpp:479:17:479:35 | [summary param] *1 in RtlCopyDeviceMemory | windows.cpp:479:17:479:35 | [summary param] *0 in RtlCopyDeviceMemory [Return] | windows.cpp:542:25:542:35 | RtlCopyDeviceMemory output argument |

View File

@@ -17,4 +17,5 @@ extensions:
- ["", "", False, "ymlStepGenerated", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
- ["", "", False, "ymlStepManual_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
- ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"]
- ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"]
- ["", "", False, "callWithNonTypeTemplate<T>", "(const T &)", "", "Argument[*0]", "ReturnValue", "value", "manual"]

View File

@@ -13,3 +13,5 @@
| test.cpp:75:11:75:11 | y | test-sink |
| test.cpp:83:11:83:11 | y | test-sink |
| test.cpp:89:11:89:11 | y | test-sink |
| test.cpp:116:10:116:11 | y1 | test-sink |
| test.cpp:119:10:119:11 | y2 | test-sink |

View File

@@ -2,6 +2,7 @@
| test.cpp:10:10:10:18 | call to ymlSource | local |
| test.cpp:56:8:56:16 | call to ymlSource | local |
| test.cpp:94:10:94:18 | call to ymlSource | local |
| test.cpp:114:10:114:18 | call to ymlSource | local |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | local |
| windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | local |
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local |

View File

@@ -102,4 +102,19 @@ void test_callWithArgument() {
}
callWithArgument(StructWithOperatorCall_has_constructor_2(), x);
callWithArgument(StructWithOperatorCall_no_constructor_2(), x);
}
}
template<int N, typename T>
T callWithNonTypeTemplate(const T&);
template<typename T, int N>
T callWithNonTypeTemplate(const T&);
void test_callWithNonTypeTemplate() {
int x = ymlSource();
int y1 = callWithNonTypeTemplate<10, int>(x);
ymlSink(y1); // $ MISSING: ir
int y2 = callWithNonTypeTemplate<int, 10>(x);
ymlSink(y2); // $ ir
}

View File

@@ -142,6 +142,7 @@ postWithInFlow
| simple.cpp:92:7:92:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
| simple.cpp:118:7:118:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
| simple.cpp:124:5:124:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| simple.cpp:167:9:167:9 | x [post update] | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge
uniqueParameterNodeAtPosition
uniqueParameterNodePosition

View File

@@ -308,3 +308,5 @@ WARNING: module 'DataFlow' has been deprecated and may be removed in future (par
| simple.cpp:124:5:124:6 | * ... | AST only |
| simple.cpp:131:14:131:14 | a | IR only |
| simple.cpp:136:10:136:10 | a | IR only |
| simple.cpp:167:9:167:9 | x | AST only |
| simple.cpp:168:8:168:12 | u_int | IR only |

View File

@@ -670,6 +670,8 @@
| simple.cpp:131:14:131:14 | a |
| simple.cpp:135:20:135:20 | q |
| simple.cpp:136:10:136:10 | a |
| simple.cpp:167:3:167:7 | u_int |
| simple.cpp:168:8:168:12 | u_int |
| struct_init.c:15:8:15:9 | ab |
| struct_init.c:15:12:15:12 | a |
| struct_init.c:16:8:16:9 | ab |

View File

@@ -597,6 +597,8 @@ WARNING: module 'DataFlow' has been deprecated and may be removed in future (par
| simple.cpp:118:7:118:7 | i |
| simple.cpp:124:5:124:6 | * ... |
| simple.cpp:135:20:135:20 | q |
| simple.cpp:167:3:167:7 | u_int |
| simple.cpp:167:9:167:9 | x |
| struct_init.c:15:8:15:9 | ab |
| struct_init.c:15:12:15:12 | a |
| struct_init.c:16:8:16:9 | ab |

View File

@@ -136,4 +136,36 @@ void alias_with_fields(bool b) {
sink(a.i); // $ MISSING: ast,ir
}
template<typename T>
union U_with_two_instantiations_of_different_size {
int x;
T y;
};
struct LargeStruct {
int data[64];
};
void test_union_with_two_instantiations_of_different_sizes() {
// A union's fields is partitioned into "chunks" for field-flow in order to
// improve performance (so that a write to a field of a union does not flow
// to too many reads that don't happen at runtime). The partitioning is based
// the size of the types in the union. So a write to a field of size k only
// flows to a read of size k.
// Since field-flow is based on uninstantiated types a field can have
// multiple sizes if the union is instantiated with types of
// different sizes. So to compute the partition we pick the maximum size.
// Because of this there are `Content`s corresponding to the union
// `U_with_two_instantiations_of_different_size<T>`: The one for size
// `sizeof(int)`, and the one for size `sizeof(LargeStruct)` (because
// `LargeStruct` is larger than `int`). So the write to `x` writes to the
// `Content` for size `sizeof(int)`, and the read of `y` reads from the
// `Content` for size `sizeof(LargeStruct)`.
U_with_two_instantiations_of_different_size<int> u_int;
U_with_two_instantiations_of_different_size<LargeStruct> u_very_large;
u_int.x = user_input();
sink(u_int.y); // $ MISSING: ir
}
} // namespace Simple

View File

@@ -26843,6 +26843,24 @@ getParameterTypeName
| atl.cpp:71:5:71:17 | _U_STRINGorID | 0 | unsigned int |
| atl.cpp:72:5:72:17 | _U_STRINGorID | 0 | LPCTSTR |
| atl.cpp:72:5:72:17 | _U_STRINGorID | 0 | const char * |
| atl.cpp:96:5:96:10 | CA2AEX | 0 | LPCSTR |
| atl.cpp:96:5:96:10 | CA2AEX | 0 | const char * |
| atl.cpp:96:5:96:10 | CA2AEX | 1 | UINT |
| atl.cpp:96:5:96:10 | CA2AEX | 1 | unsigned int |
| atl.cpp:97:5:97:10 | CA2AEX | 0 | LPCSTR |
| atl.cpp:97:5:97:10 | CA2AEX | 0 | const char * |
| atl.cpp:124:5:124:11 | CA2CAEX | 0 | LPCSTR |
| atl.cpp:124:5:124:11 | CA2CAEX | 0 | const char * |
| atl.cpp:124:5:124:11 | CA2CAEX | 1 | UINT |
| atl.cpp:124:5:124:11 | CA2CAEX | 1 | unsigned int |
| atl.cpp:125:5:125:11 | CA2CAEX | 0 | LPCSTR |
| atl.cpp:125:5:125:11 | CA2CAEX | 0 | const char * |
| atl.cpp:149:5:149:10 | CA2WEX | 0 | LPCSTR |
| atl.cpp:149:5:149:10 | CA2WEX | 0 | const char * |
| atl.cpp:149:5:149:10 | CA2WEX | 1 | UINT |
| atl.cpp:149:5:149:10 | CA2WEX | 1 | unsigned int |
| atl.cpp:150:5:150:10 | CA2WEX | 0 | LPCSTR |
| atl.cpp:150:5:150:10 | CA2WEX | 0 | const char * |
| atl.cpp:196:12:196:14 | Add | 0 | INARGTYPclass:0 |
| atl.cpp:198:12:198:17 | Append | 0 | const CAtlArray & |
| atl.cpp:199:10:199:13 | Copy | 0 | const CAtlArray & |
@@ -27083,6 +27101,10 @@ getParameterTypeName
| atl.cpp:940:10:940:18 | SetString | 0 | PCXSTR |
| atl.cpp:940:10:940:18 | SetString | 0 | const class:0 * |
| atl.cpp:942:11:942:20 | operator[] | 0 | int |
| atl.cpp:1018:10:1018:10 | operator= | 0 | MakeOther && |
| atl.cpp:1018:10:1018:10 | operator= | 0 | const MakeOther & |
| atl.cpp:1023:10:1023:10 | operator= | 0 | MakeOther && |
| atl.cpp:1023:10:1023:10 | operator= | 0 | const MakeOther & |
| atl.cpp:1036:5:1036:12 | CStringT | 0 | const VARIANT & |
| atl.cpp:1036:5:1036:12 | CStringT | 0 | const tagVARIANT & |
| atl.cpp:1037:5:1037:12 | CStringT | 0 | const VARIANT & |
@@ -27286,6 +27308,8 @@ getParameterTypeName
| standalone_iterators.cpp:20:7:20:7 | operator= | 0 | const int_iterator_by_trait & |
| standalone_iterators.cpp:20:7:20:7 | operator= | 0 | int_iterator_by_trait && |
| standalone_iterators.cpp:23:27:23:36 | operator++ | 0 | int |
| standalone_iterators.cpp:28:13:28:13 | operator= | 0 | const iterator_traits & |
| standalone_iterators.cpp:28:13:28:13 | operator= | 0 | iterator_traits && |
| standalone_iterators.cpp:36:7:36:7 | operator= | 0 | const non_iterator & |
| standalone_iterators.cpp:36:7:36:7 | operator= | 0 | non_iterator && |
| standalone_iterators.cpp:39:18:39:27 | operator++ | 0 | int |
@@ -27297,6 +27321,8 @@ getParameterTypeName
| standalone_iterators.cpp:66:30:66:39 | operator++ | 0 | int |
| standalone_iterators.cpp:68:30:68:39 | operator-- | 0 | int |
| standalone_iterators.cpp:70:31:70:39 | operator= | 0 | int |
| standalone_iterators.cpp:74:13:74:13 | operator= | 0 | const iterator_traits & |
| standalone_iterators.cpp:74:13:74:13 | operator= | 0 | iterator_traits && |
| standalone_iterators.cpp:82:7:82:7 | container | 0 | const container & |
| standalone_iterators.cpp:82:7:82:7 | container | 0 | container && |
| standalone_iterators.cpp:82:7:82:7 | operator= | 0 | const container & |

View File

@@ -2,10 +2,10 @@
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | address && | SemanticStackVariable | | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | const __va_list_tag & | SemanticStackVariable | | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | const address & | SemanticStackVariable | | |
| file://:0:0:0:0 | fp_offset | file://:0:0:0:0 | unsigned int | Field | | |
| file://:0:0:0:0 | gp_offset | file://:0:0:0:0 | unsigned int | Field | | |
| file://:0:0:0:0 | overflow_arg_area | file://:0:0:0:0 | void * | Field | | |
| file://:0:0:0:0 | reg_save_area | file://:0:0:0:0 | void * | Field | | |
| file://:0:0:0:0 | fp_offset | file://:0:0:0:0 | unsigned int | NonLocalCanonicalField | | |
| file://:0:0:0:0 | gp_offset | file://:0:0:0:0 | unsigned int | NonLocalCanonicalField | | |
| file://:0:0:0:0 | overflow_arg_area | file://:0:0:0:0 | void * | NonLocalCanonicalField | | |
| file://:0:0:0:0 | reg_save_area | file://:0:0:0:0 | void * | NonLocalCanonicalField | | |
| variables.cpp:1:12:1:12 | i | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
| variables.cpp:2:12:2:12 | i | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
| variables.cpp:3:12:3:12 | i | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
@@ -33,10 +33,10 @@
| variables.cpp:37:6:37:8 | ap3 | file://:0:0:0:0 | int * | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
| variables.cpp:41:7:41:11 | local | file://:0:0:0:0 | char[] | LocalVariable, SemanticStackVariable | | |
| variables.cpp:43:14:43:18 | local | file://:0:0:0:0 | int | GlobalLikeVariable, StaticLocalVariable | | static |
| variables.cpp:48:9:48:12 | name | file://:0:0:0:0 | char * | Field | | |
| variables.cpp:49:12:49:17 | number | file://:0:0:0:0 | long | Field | | |
| variables.cpp:50:9:50:14 | street | file://:0:0:0:0 | char * | Field | | |
| variables.cpp:51:9:51:12 | town | file://:0:0:0:0 | char * | Field | | |
| variables.cpp:48:9:48:12 | name | file://:0:0:0:0 | char * | NonLocalCanonicalField | | |
| variables.cpp:49:12:49:17 | number | file://:0:0:0:0 | long | NonLocalCanonicalField | | |
| variables.cpp:50:9:50:14 | street | file://:0:0:0:0 | char * | NonLocalCanonicalField | | |
| variables.cpp:51:9:51:12 | town | file://:0:0:0:0 | char * | NonLocalCanonicalField | | |
| variables.cpp:52:16:52:22 | country | file://:0:0:0:0 | char * | MemberVariable, StaticStorageDurationVariable | | static |
| variables.cpp:56:14:56:29 | externInFunction | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
| variables.cpp:60:10:60:17 | __func__ | file://:0:0:0:0 | const char[9] | GlobalLikeVariable, StaticInitializedStaticLocalVariable | | static |

View File

@@ -1,5 +1,5 @@
/**
* @name Container size compared to zero.
* @name Container size compared to zero
* @description Comparing the size of a container to zero with this operator will always return the same value.
* @kind problem
* @problem.severity warning

View File

@@ -1,5 +1,5 @@
/**
* @name Do not add certificates to the system root store.
* @name Do not add certificates to the system root store
* @description Application- or user-specific certificates placed in the system root store could
* weaken security for other processing running on the same system.
* @kind path-problem

View File

@@ -1,5 +1,5 @@
/**
* @name Unsafe usage of v1 version of Azure Storage client-side encryption (CVE-2022-30187).
* @name Unsafe usage of v1 version of Azure Storage client-side encryption (CVE-2022-30187)
* @description Unsafe usage of v1 version of Azure Storage client-side encryption, please refer to http://aka.ms/azstorageclientencryptionblog
* @kind problem
* @tags security

View File

@@ -1,5 +1,5 @@
/**
* @name Extract MaD neutral model rows.
* @name Extract MaD neutral model rows
* @description This extracts the Models as data neutral model rows.
* @id cs/utils/modelconverter/generate-data-extensions-neutral
*/

View File

@@ -1,5 +1,5 @@
/**
* @name Extract MaD sink model rows.
* @name Extract MaD sink model rows
* @description This extracts the Models as data sink model rows.
* @id cs/utils/modelconverter/generate-data-extensions-sink
*/

View File

@@ -1,5 +1,5 @@
/**
* @name Extract MaD source model rows.
* @name Extract MaD source model rows
* @description This extracts the Models as data source model rows.
* @id cs/utils/modelconverter/generate-data-extensions-source
*/

View File

@@ -1,5 +1,5 @@
/**
* @name Extract MaD summary model rows.
* @name Extract MaD summary model rows
* @description This extracts the Models as data summary model rows.
* @id cs/utils/modelconverter/generate-data-extensions-summary
*/

View File

@@ -1,5 +1,5 @@
/**
* @name Capture content based summary models.
* @name Capture content based summary models
* @description Finds applicable content based summary models to be used by other queries.
* @kind diagnostic
* @id cs/utils/modelgenerator/contentbased-summary-models

View File

@@ -1,5 +1,5 @@
/**
* @name Capture neutral models.
* @name Capture neutral models
* @description Finds neutral models to be used by other queries.
* @kind diagnostic
* @id cs/utils/modelgenerator/neutral-models

View File

@@ -1,5 +1,5 @@
/**
* @name Capture sink models.
* @name Capture sink models
* @description Finds public methods that act as sinks as they flow into a known sink.
* @kind diagnostic
* @id cs/utils/modelgenerator/sink-models

View File

@@ -1,5 +1,5 @@
/**
* @name Capture source models.
* @name Capture source models
* @description Finds APIs that act as sources as they expose already known sources.
* @kind diagnostic
* @id cs/utils/modelgenerator/source-models

View File

@@ -1,5 +1,5 @@
/**
* @name Capture summary models.
* @name Capture summary models
* @description Finds applicable summary models to be used by other queries.
* @kind diagnostic
* @id cs/utils/modelgenerator/summary-models

View File

@@ -1,5 +1,5 @@
/**
* @name Capture typed based summary models.
* @name Capture typed based summary models
* @description Finds applicable summary models to be used by other queries.
* @kind diagnostic
* @id cs/utils/modelgenerator/summary-models-typed-based

View File

@@ -1,5 +1,5 @@
/**
* @name Tests call graph.
* @name Tests call graph
*/
import csharp

View File

@@ -1,5 +1,5 @@
/**
* @name Test the implicit switch field isn't populated.
* @name Test the implicit switch field isn't populated
*/
import csharp

View File

@@ -12,6 +12,7 @@ ql/go/ql/src/Security/CWE-079/HtmlTemplateEscapingBypassXss.ql
ql/go/ql/src/Security/CWE-079/ReflectedXss.ql
ql/go/ql/src/Security/CWE-089/SqlInjection.ql
ql/go/ql/src/Security/CWE-089/StringBreak.ql
ql/go/ql/src/Security/CWE-1004/CookieWithoutHttpOnly.ql
ql/go/ql/src/Security/CWE-190/AllocationSizeOverflow.ql
ql/go/ql/src/Security/CWE-209/StackTraceExposure.ql
ql/go/ql/src/Security/CWE-295/DisabledCertificateCheck.ql
@@ -26,6 +27,7 @@ ql/go/ql/src/Security/CWE-347/MissingJwtSignatureCheck.ql
ql/go/ql/src/Security/CWE-352/ConstantOauth2State.ql
ql/go/ql/src/Security/CWE-601/BadRedirectCheck.ql
ql/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql
ql/go/ql/src/Security/CWE-614/CookieWithoutSecure.ql
ql/go/ql/src/Security/CWE-640/EmailInjection.ql
ql/go/ql/src/Security/CWE-643/XPathInjection.ql
ql/go/ql/src/Security/CWE-681/IncorrectIntegerConversionQuery.ql

View File

@@ -34,6 +34,7 @@ ql/go/ql/src/Security/CWE-079/HtmlTemplateEscapingBypassXss.ql
ql/go/ql/src/Security/CWE-079/ReflectedXss.ql
ql/go/ql/src/Security/CWE-089/SqlInjection.ql
ql/go/ql/src/Security/CWE-089/StringBreak.ql
ql/go/ql/src/Security/CWE-1004/CookieWithoutHttpOnly.ql
ql/go/ql/src/Security/CWE-117/LogInjection.ql
ql/go/ql/src/Security/CWE-190/AllocationSizeOverflow.ql
ql/go/ql/src/Security/CWE-209/StackTraceExposure.ql
@@ -49,6 +50,7 @@ ql/go/ql/src/Security/CWE-347/MissingJwtSignatureCheck.ql
ql/go/ql/src/Security/CWE-352/ConstantOauth2State.ql
ql/go/ql/src/Security/CWE-601/BadRedirectCheck.ql
ql/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql
ql/go/ql/src/Security/CWE-614/CookieWithoutSecure.ql
ql/go/ql/src/Security/CWE-640/EmailInjection.ql
ql/go/ql/src/Security/CWE-643/XPathInjection.ql
ql/go/ql/src/Security/CWE-681/IncorrectIntegerConversionQuery.ql

View File

@@ -12,6 +12,7 @@ ql/go/ql/src/Security/CWE-079/HtmlTemplateEscapingBypassXss.ql
ql/go/ql/src/Security/CWE-079/ReflectedXss.ql
ql/go/ql/src/Security/CWE-089/SqlInjection.ql
ql/go/ql/src/Security/CWE-089/StringBreak.ql
ql/go/ql/src/Security/CWE-1004/CookieWithoutHttpOnly.ql
ql/go/ql/src/Security/CWE-117/LogInjection.ql
ql/go/ql/src/Security/CWE-190/AllocationSizeOverflow.ql
ql/go/ql/src/Security/CWE-209/StackTraceExposure.ql
@@ -27,6 +28,7 @@ ql/go/ql/src/Security/CWE-347/MissingJwtSignatureCheck.ql
ql/go/ql/src/Security/CWE-352/ConstantOauth2State.ql
ql/go/ql/src/Security/CWE-601/BadRedirectCheck.ql
ql/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql
ql/go/ql/src/Security/CWE-614/CookieWithoutSecure.ql
ql/go/ql/src/Security/CWE-640/EmailInjection.ql
ql/go/ql/src/Security/CWE-643/XPathInjection.ql
ql/go/ql/src/Security/CWE-681/IncorrectIntegerConversionQuery.ql

View File

@@ -9,7 +9,6 @@ ql/go/ql/src/Security/CWE-079/StoredXss.ql
ql/go/ql/src/Security/CWE-798/HardcodedCredentials.ql
ql/go/ql/src/definitions.ql
ql/go/ql/src/experimental/CWE-090/LDAPInjection.ql
ql/go/ql/src/experimental/CWE-1004/CookieWithoutHttpOnly.ql
ql/go/ql/src/experimental/CWE-203/Timing.ql
ql/go/ql/src/experimental/CWE-285/PamAuthBypass.ql
ql/go/ql/src/experimental/CWE-287/ImproperLdapAuth.ql

View File

@@ -41,6 +41,7 @@ import semmle.go.frameworks.ElazarlGoproxy
import semmle.go.frameworks.Email
import semmle.go.frameworks.Encoding
import semmle.go.frameworks.Fasthttp
import semmle.go.frameworks.Gin
import semmle.go.frameworks.GinCors
import semmle.go.frameworks.Glog
import semmle.go.frameworks.GoJose

View File

@@ -380,4 +380,96 @@ module Http {
/** Gets a node that is used in a check that is tested before this handler is run. */
predicate guardedBy(DataFlow::Node check) { super.guardedBy(check) }
}
/** Provides a class for modeling new HTTP response cookie write APIs. */
module CookieWrite {
/**
* A write of an HTTP Cookie to an HTTP response.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `HTTP::CookieWrite` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets the name of the cookie written. */
abstract DataFlow::Node getName();
/** Gets the value of the cookie written. */
abstract DataFlow::Node getValue();
/** Gets the `Secure` attribute of the cookie written. */
abstract DataFlow::Node getSecure();
/** Gets the `HttpOnly` attribute of the cookie written. */
abstract DataFlow::Node getHttpOnly();
}
}
/**
* A write of an HTTP Cookie to an HTTP response.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `HTTP::CookieWrite::Range` instead.
*/
class CookieWrite extends DataFlow::Node instanceof CookieWrite::Range {
/** Gets the name of the cookie written. */
DataFlow::Node getName() { result = super.getName() }
/** Gets the value of the cookie written. */
DataFlow::Node getValue() { result = super.getValue() }
/** Gets the `Secure` attribute of the cookie written. */
DataFlow::Node getSecure() { result = super.getSecure() }
/** Gets the `HttpOnly` attribute of the cookie written. */
DataFlow::Node getHttpOnly() { result = super.getHttpOnly() }
}
/** Provides a class for modeling the new APIs for writes to options of an HTTP cookie. */
module CookieOptionWrite {
/**
* A write to an option of an HTTP cookie object.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `HTTP::CookieOptionWrite` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets the node representing the cookie object for the options being set. */
abstract DataFlow::Node getCookieOutput();
/** Gets the name of the cookie represented, if any. */
abstract DataFlow::Node getName();
/** Gets the value of the cookie represented, if any. */
abstract DataFlow::Node getValue();
/** Gets the `Secure` attribute of the cookie represented, if any. */
abstract DataFlow::Node getSecure();
/** Gets the `HttpOnly` attribute of the cookie represented, if any. */
abstract DataFlow::Node getHttpOnly();
}
}
/**
* A write to an option of an HTTP cookie object.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `HTTP::CookieOptionWrite::Range` instead.
*/
class CookieOptionWrite extends DataFlow::Node instanceof CookieOptionWrite::Range {
/** Gets the node representing the cookie object for the options being set. */
DataFlow::Node getCookieOutput() { result = super.getCookieOutput() }
/** Gets the name of the cookie represented, if any. */
DataFlow::Node getName() { result = super.getName() }
/** Gets the value of the cookie represented, if any. */
DataFlow::Node getValue() { result = super.getValue() }
/** Gets the `Secure` attribute of the cookie represented, if any. */
DataFlow::Node getSecure() { result = super.getSecure() }
/** Gets the `HttpOnly` attribute of the cookie represented, if any. */
DataFlow::Node getHttpOnly() { result = super.getHttpOnly() }
}
}

View File

@@ -0,0 +1,24 @@
/**
* Provides classes for modeling the `github.com/gin-gonic/gin` package.
*/
import go
import semmle.go.concepts.HTTP
/** Provides models for the `gin-gonic/gin` package. */
module Gin {
/** Gets the package name `github.com/gin-gonic/gin`. */
string packagePath() { result = package("github.com/gin-gonic/gin", "") }
private class GinCookieWrite extends Http::CookieWrite::Range, DataFlow::MethodCallNode {
GinCookieWrite() { this.getTarget().hasQualifiedName(packagePath(), "Context", "SetCookie") }
override DataFlow::Node getName() { result = this.getArgument(0) }
override DataFlow::Node getValue() { result = this.getArgument(1) }
override DataFlow::Node getSecure() { result = this.getArgument(5) }
override DataFlow::Node getHttpOnly() { result = this.getArgument(6) }
}
}

View File

@@ -293,4 +293,38 @@ module NetHttp {
override DataFlow::Node getAPathArgument() { result = this.getArgument(2) }
}
private class CookieWrite extends Http::CookieWrite::Range, DataFlow::CallNode {
CookieWrite() { this.getTarget().hasQualifiedName(package("net/http", ""), "SetCookie") }
override DataFlow::Node getName() { result = this.getArgument(1) }
override DataFlow::Node getValue() { result = this.getArgument(1) }
override DataFlow::Node getSecure() { result = this.getArgument(1) }
override DataFlow::Node getHttpOnly() { result = this.getArgument(1) }
}
private class CookieFieldWrite extends Http::CookieOptionWrite::Range {
DataFlow::Node written;
string fieldName;
CookieFieldWrite() {
exists(Write w, Field f |
f.hasQualifiedName(package("net/http", ""), "Cookie", fieldName) and
w.writesField(this, f, written)
)
}
override DataFlow::Node getCookieOutput() { result = this }
override DataFlow::Node getName() { fieldName = "Name" and result = written }
override DataFlow::Node getValue() { fieldName = "Value" and result = written }
override DataFlow::Node getSecure() { fieldName = "Secure" and result = written }
override DataFlow::Node getHttpOnly() { fieldName = "HttpOnly" and result = written }
}
}

View File

@@ -0,0 +1,77 @@
/** Provides classes and predicates for identifying HTTP cookies without the `HttpOnly` attribute. */
import go
import semmle.go.concepts.HTTP
import semmle.go.dataflow.DataFlow
private module SensitiveCookieNameConfig implements DataFlow::ConfigSig {
/**
* Holds if `source` is an expression with a name or literal value `val` indicating a sensitive cookie.
*/
additional predicate isSource(DataFlow::Node source, string val) {
(
val = source.asExpr().getStringValue() or
val = source.asExpr().(Name).getTarget().getName()
) and
val.regexpMatch("(?i).*(session|login|token|user|auth|credential).*") and
not val.regexpMatch("(?i).*(xsrf|csrf|forgery).*")
}
predicate isSource(DataFlow::Node source) { isSource(source, _) }
additional predicate isSink(DataFlow::Node sink, Http::CookieWrite cw) { sink = cw.getName() }
predicate isSink(DataFlow::Node sink) { isSink(sink, _) }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Http::CookieOptionWrite co | co.getName() = pred and co.getCookieOutput() = succ)
}
}
/** Tracks flow from sensitive names to HTTP cookie writes. */
module SensitiveCookieNameFlow = TaintTracking::Global<SensitiveCookieNameConfig>;
private module BooleanCookieHttpOnlyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getType().getUnderlyingType() instanceof BoolType
}
predicate isSink(DataFlow::Node sink) { exists(Http::CookieWrite cw | sink = cw.getHttpOnly()) }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Http::CookieOptionWrite co | co.getHttpOnly() = pred and co.getCookieOutput() = succ)
}
}
/** Tracks flow from boolean expressions to the `HttpOnly` attribute of HTTP cookie writes. */
module BooleanCookieHttpOnlyFlow = TaintTracking::Global<BooleanCookieHttpOnlyConfig>;
/** Holds if `cw` has the `HttpOnly` attribute left at its default value of `false`. */
predicate isNonHttpOnlyDefault(Http::CookieWrite cw) {
not BooleanCookieHttpOnlyFlow::flowTo(cw.getHttpOnly())
}
/** Holds if `cw` has the `HttpOnly` attribute explicitly set to `false`, from the expression `boolFalse`. */
predicate isNonHttpOnlyDirect(Http::CookieWrite cw, Expr boolFalse) {
BooleanCookieHttpOnlyFlow::flow(DataFlow::exprNode(boolFalse), cw.getHttpOnly()) and
boolFalse.getBoolValue() = false
}
/** Holds if `cw` has the `HttpOnly` attribute set to `false`, either explicitly or by default. */
predicate isNonHttpOnlyCookie(Http::CookieWrite cw) {
isNonHttpOnlyDefault(cw) or
isNonHttpOnlyDirect(cw, _)
}
/**
* Holds if `cw` has the sensitive name `name`, from the expression `nameExpr`.
* `source` and `sink` represent the data flow path from the sensitive name expression to the cookie write.
*/
predicate isSensitiveCookie(
Http::CookieWrite cw, string name, SensitiveCookieNameFlow::PathNode source,
SensitiveCookieNameFlow::PathNode sink
) {
SensitiveCookieNameFlow::flowPath(source, sink) and
SensitiveCookieNameConfig::isSource(source.getNode(), name) and
SensitiveCookieNameConfig::isSink(sink.getNode(), cw)
}

View File

@@ -0,0 +1,37 @@
/** Provides classes and predicates for identifying HTTP cookies without the `Secure` attribute. */
import go
import semmle.go.concepts.HTTP
import semmle.go.dataflow.DataFlow
private module BooleanCookieSecureConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getType().getUnderlyingType() instanceof BoolType
}
predicate isSink(DataFlow::Node sink) { exists(Http::CookieWrite cw | sink = cw.getSecure()) }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Http::CookieOptionWrite co | co.getSecure() = pred and co.getCookieOutput() = succ)
}
}
/** Tracks flow from boolean expressions to the `Secure` attribute of HTTP cookie writes. */
module BooleanCookieSecureFlow = TaintTracking::Global<BooleanCookieSecureConfig>;
/** Holds if `cw` has the `Secure` attribute left at its default value of `false`. */
predicate isInsecureDefault(Http::CookieWrite cw) {
not BooleanCookieSecureFlow::flowTo(cw.getSecure())
}
/** Holds if `cw` has the `Secure` attribute explicitly set to `false`, from the expression `boolFalse`. */
predicate isInsecureDirect(Http::CookieWrite cw, Expr boolFalse) {
BooleanCookieSecureFlow::flow(DataFlow::exprNode(boolFalse), cw.getSecure()) and
boolFalse.getBoolValue() = false
}
/** Holds if `cw` has the `Secure` attribute set to `false`, either explicitly or by default. */
predicate isInsecureCookie(Http::CookieWrite cw) {
isInsecureDefault(cw) or
isInsecureDirect(cw, _)
}

View File

@@ -0,0 +1,34 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Cookies without the <code>HttpOnly</code> flag set are accessible to client-side scripts such as JavaScript running in the same origin.
In case of a Cross-Site Scripting (XSS) vulnerability, the cookie can be stolen by a malicious script.
If a sensitive cookie does not need to be accessed directly by client-side JS, the <code>HttpOnly</code> flag should be set.</p>
</overview>
<recommendation>
<p>
Set the <code>HttpOnly</code> flag to <code>true</code> for authentication cookies to ensure they are not accessible to client-side scripts.
</p>
</recommendation>
<example>
<p>
In the following example, in the case marked BAD, the <code>HttpOnly</code> flag is not set, so the default value of <code>false</code> is used.
In the case marked GOOD, the <code>HttpOnly</code> flag is set to <code>true</code>.
</p>
<sample src="examples/CookieWithoutHttpOnly.go"/>
</example>
<references>
<li>MDN: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">Set-Cookie</a> Header.</li>
<li>PortSwigger: <a href="https://portswigger.net/kb/issues/00500600_cookie-without-httponly-flag-set">Cookie without HttpOnly flag set</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,25 @@
/**
* @name Cookie 'HttpOnly' attribute is not set to true
* @description Sensitive cookies without the `HttpOnly` property set are accessible by client-side scripts such as JavaScript.
* This makes them more vulnerable to being stolen by an XSS attack.
* @kind path-problem
* @problem.severity warning
* @precision high
* @security-severity 5.0
* @id go/cookie-httponly-not-set
* @tags security
* external/cwe/cwe-1004
*/
import go
import semmle.go.security.CookieWithoutHttpOnly
import SensitiveCookieNameFlow::PathGraph
from
Http::CookieWrite cw, string name, SensitiveCookieNameFlow::PathNode source,
SensitiveCookieNameFlow::PathNode sink
where
isSensitiveCookie(cw, name, source, sink) and
isNonHttpOnlyCookie(cw)
select cw, source, sink, "Sensitive cookie $@ does not set HttpOnly attribute to true.", source,
name

View File

@@ -0,0 +1,22 @@
package main
import (
"net/http"
)
func handlerBad(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
http.SetCookie(w, &c) // BAD: The HttpOnly flag is set to false by default.
}
func handlerGood(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: true,
}
http.SetCookie(w, &c) // GOOD: The HttpOnly flag is set to true.
}

View File

@@ -0,0 +1,35 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Cookies without the <code>Secure</code> flag set may be transmitted using HTTP instead of HTTPS.
This leaves them vulnerable to being read by a third party attacker. If a sensitive cookie such as a session
key is intercepted this way, it would allow the attacker to perform actions on a user's behalf.</p>
</overview>
<recommendation>
<p>
Set the <code>Secure</code> flag to <code>true</code> to ensure cookies are only transmitted over secure HTTPS connections.
</p>
</recommendation>
<example>
<p>
In the following example, in the case marked BAD, the <code>Secure</code> flag is set to <code>false</code> by default.
In the case marked GOOD, the <code>Secure</code> flag is set to <code>true</code>.
</p>
<sample src="examples/CookieWithoutSecure.go"/>
</example>
<references>
<li>MDN: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">Set-Cookie</a> Header.</li>
<li>Detectify: <a href="https://support.detectify.com/support/solutions/articles/48001048982-cookie-lack-secure-flag">Cookie lack Secure flag</a>.</li>
<li>PortSwigger: <a href="https://portswigger.net/kb/issues/00500200_tls-cookie-without-secure-flag-set">TLS cookie without secure flag set</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,19 @@
/**
* @name Cookie 'Secure' attribute is not set to true
* @description Cookies without the `Secure` flag may be sent in cleartext.
* This makes them vulnerable to be intercepted by an attacker.
* @kind problem
* @problem.severity warning
* @precision high
* @security-severity 4.0
* @id go/cookie-secure-not-set
* @tags security
* external/cwe/cwe-614
*/
import go
import semmle.go.security.CookieWithoutSecure
from Http::CookieWrite cw
where isInsecureCookie(cw)
select cw, "Cookie does not set Secure attribute to true."

View File

@@ -0,0 +1,22 @@
package main
import (
"net/http"
)
func handlerBad(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
http.SetCookie(w, &c) // BAD: The Secure flag is set to false by default.
}
func handlerGood(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
Secure: true,
}
http.SetCookie(w, &c) // GOOD: The Secure flag is set to true.
}

View File

@@ -0,0 +1,5 @@
---
category: newQuery
---
* The `go/cookie-http-only-not-set` query has been promoted from the experimental query pack. This query was originally contributed to the experimental query pack by @edvraa.
* A new query `go/cookie-secure-not-set` has been added to detect cookies without the `Secure` flag set.

View File

@@ -1,245 +0,0 @@
import go
private class NetHttpCookieType extends Type {
NetHttpCookieType() { this.hasQualifiedName(package("net/http", ""), "Cookie") }
}
private class GinContextSetCookieMethod extends Method {
GinContextSetCookieMethod() {
this.hasQualifiedName(package("github.com/gin-gonic/gin", ""), "Context", "SetCookie")
}
}
private class GorillaSessionOptionsField extends Field {
GorillaSessionOptionsField() {
this.hasQualifiedName(package("github.com/gorilla/sessions", ""), "Session", "Options")
}
}
/**
* A simplistic points-to alternative: given a struct creation and a field name, get the values that field can be assigned.
*
* Assumptions:
* - we don't reassign the variable that the creation is stored in
* - we always access the creation through the same variable it is initially assigned to
*
* This should cover most typical patterns...
*/
private DataFlow::Node getValueForFieldWrite(StructLit sl, string field) {
exists(Write w, DataFlow::Node base, Field f |
f.getName() = field and
w.writesFieldPreUpdate(base, f, result) and
(
sl = base.asExpr()
or
base.asExpr() instanceof VariableName and
base.getAPredecessor*().asExpr() = sl
)
)
}
/**
* Holds if the expression or its value has a sensitive name
*/
private predicate isAuthVariable(Expr expr) {
exists(string val |
(
val = expr.getStringValue() or
val = expr.(Name).getTarget().getName()
) and
val.regexpMatch("(?i).*(session|login|token|user|auth|credential).*") and
not val.regexpMatch("(?i).*(xsrf|csrf|forgery).*")
)
}
/**
* A cookie passed as the second parameter to `net/http.SetCookie`.
*/
private class SetCookieSink extends DataFlow::Node {
SetCookieSink() {
exists(DataFlow::CallNode cn |
cn.getTarget().hasQualifiedName(package("net/http", ""), "SetCookie") and
this = cn.getArgument(1)
)
}
}
private module NameToNetHttpCookieTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isAuthVariable(source.asExpr()) }
predicate isSink(DataFlow::Node sink) { sink instanceof SetCookieSink }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(StructLit sl |
sl.getType() instanceof NetHttpCookieType and
getValueForFieldWrite(sl, "Name") = pred and
sl = succ.asExpr()
)
}
}
/** Tracks taint flow from sensitive names to `net/http.SetCookie`. */
module NameToNetHttpCookieTrackingFlow = TaintTracking::Global<NameToNetHttpCookieTrackingConfig>;
private module BoolToNetHttpCookieTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getType().getUnderlyingType() instanceof BoolType
}
predicate isSink(DataFlow::Node sink) { sink instanceof SetCookieSink }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(StructLit sl |
sl.getType() instanceof NetHttpCookieType and
getValueForFieldWrite(sl, "HttpOnly") = pred and
sl = succ.asExpr()
)
}
}
/**
* Tracks taint flow from a `bool` assigned to `HttpOnly` to
* `net/http.SetCookie`.
*/
module BoolToNetHttpCookieTrackingFlow = TaintTracking::Global<BoolToNetHttpCookieTrackingConfig>;
private module BoolToGinSetCookieTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.getBoolValue() = false }
predicate isSink(DataFlow::Node sink) {
exists(DataFlow::MethodCallNode mcn |
mcn.getTarget() instanceof GinContextSetCookieMethod and
mcn.getArgument(6) = sink and
exists(DataFlow::Node nameArg |
NameToGinSetCookieTrackingFlow::flowTo(nameArg) and
mcn.getArgument(0) = nameArg
)
)
}
predicate observeDiffInformedIncrementalMode() {
any() // Merged with other flows in CookieWithoutHttpOnly.ql
}
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
}
/**
* Tracks data flow from `HttpOnly` set to `false` to
* `gin-gonic/gin.Context.SetCookie`.
*/
module BoolToGinSetCookieTrackingFlow = DataFlow::Global<BoolToGinSetCookieTrackingConfig>;
private module NameToGinSetCookieTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isAuthVariable(source.asExpr()) }
predicate isSink(DataFlow::Node sink) {
exists(DataFlow::MethodCallNode mcn |
mcn.getTarget() instanceof GinContextSetCookieMethod and
mcn.getArgument(0) = sink
)
}
}
/**
* Tracks taint flow from sensitive names to `gin-gonic/gin.Context.SetCookie`.
*/
private module NameToGinSetCookieTrackingFlow = DataFlow::Global<NameToGinSetCookieTrackingConfig>;
/**
* The receiver of `gorilla/sessions.Session.Save` call.
*/
private class GorillaSessionSaveSink extends DataFlow::Node {
GorillaSessionSaveSink() {
exists(DataFlow::MethodCallNode mcn |
this = mcn.getReceiver() and
mcn.getTarget()
.hasQualifiedName(package("github.com/gorilla/sessions", ""), "Session", "Save")
)
}
}
private class GorillaStoreSaveSink extends DataFlow::Node {
GorillaStoreSaveSink() {
exists(DataFlow::MethodCallNode mcn |
this = mcn.getArgument(2) and
mcn.getTarget()
.hasQualifiedName(package("github.com/gorilla/sessions", ""), "CookieStore", "Save")
)
}
}
private module GorillaCookieStoreSaveTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source
.(DataFlow::CallNode)
.getTarget()
.hasQualifiedName(package("github.com/gorilla/sessions", ""), "NewCookieStore")
}
predicate isSink(DataFlow::Node sink) {
sink instanceof GorillaSessionSaveSink or
sink instanceof GorillaStoreSaveSink
}
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(DataFlow::MethodCallNode cn |
cn.getTarget()
.hasQualifiedName(package("github.com/gorilla/sessions", ""), "CookieStore", "Get") and
pred = cn.getReceiver() and
succ = cn.getResult(0)
)
}
}
/**
* Tracks data flow from gorilla cookie store creation to
* `gorilla/sessions.Session.Save`.
*/
module GorillaCookieStoreSaveTrackingFlow = DataFlow::Global<GorillaCookieStoreSaveTrackingConfig>;
private module GorillaSessionOptionsTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(StructLit sl |
sl.getType().hasQualifiedName(package("github.com/gorilla/sessions", ""), "Options") and
source.asExpr() = sl
)
}
predicate isSink(DataFlow::Node sink) { sink instanceof GorillaSessionSaveSink }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(GorillaSessionOptionsField f, DataFlow::Write w | w.writesField(succ, f, pred))
}
}
/**
* Tracks taint flow from session options to
* `gorilla/sessions.Session.Save`.
*/
module GorillaSessionOptionsTrackingFlow =
TaintTracking::Global<GorillaSessionOptionsTrackingConfig>;
private module BoolToGorillaSessionOptionsTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getType().getUnderlyingType() instanceof BoolType
}
predicate isSink(DataFlow::Node sink) { sink instanceof GorillaSessionSaveSink }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(StructLit sl |
getValueForFieldWrite(sl, "HttpOnly") = pred and
sl = succ.asExpr()
)
or
exists(GorillaSessionOptionsField f, DataFlow::Write w | w.writesField(succ, f, pred))
}
}
/**
* Tracks taint flow from a `bool` assigned to `HttpOnly` to
* `gorilla/sessions.Session.Save`.
*/
module BoolToGorillaSessionOptionsTrackingFlow =
TaintTracking::Global<BoolToGorillaSessionOptionsTrackingConfig>;

View File

@@ -1,42 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Cookies without <code>HttpOnly</code> attribute are accessible to JavaScript running in the same origin. In case of
Cross-Site Scripting (XSS) vulnerability the cookie can be stolen by malicious script.
</p>
</overview>
<recommendation>
<p>
Protect sensitive cookies, such as related to authentication, by setting <code>HttpOnly</code> to <code>true</code> to make
them not accessible to JavaScript.
</p>
</recommendation>
<example>
<p>
In the following example the default <code>HttpOnly</code> value is <code>false</code>.
</p>
<sample src="CookieWithoutHttpOnlyBad.go" />
<p>
In the example below <code>HttpOnly</code> is set to <code>true</code>.
</p>
<sample src="CookieWithoutHttpOnlyGood.go" />
</example>
<references>
<li><a href="https://golang.org/pkg/net/http/#Cookie">type Cookie,</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">Set-Cookie</a> Header,</li>
</references>
</qhelp>

View File

@@ -1,99 +0,0 @@
/**
* @name 'HttpOnly' attribute is not set to true
* @description Omitting the 'HttpOnly' attribute for security sensitive data allows
* malicious JavaScript to steal it in case of XSS vulnerability. Always set
* 'HttpOnly' to 'true' to authentication related cookie to make it
* not accessible by JavaScript.
* @kind path-problem
* @problem.severity warning
* @precision high
* @id go/cookie-httponly-not-set
* @tags security
* experimental
* external/cwe/cwe-1004
*/
import go
import AuthCookie
module NetHttpCookieTrackingFlow =
DataFlow::MergePathGraph<NameToNetHttpCookieTrackingFlow::PathNode,
BoolToNetHttpCookieTrackingFlow::PathNode, NameToNetHttpCookieTrackingFlow::PathGraph,
BoolToNetHttpCookieTrackingFlow::PathGraph>;
module GorillaTrackingFlow =
DataFlow::MergePathGraph3<GorillaCookieStoreSaveTrackingFlow::PathNode,
GorillaSessionOptionsTrackingFlow::PathNode, BoolToGorillaSessionOptionsTrackingFlow::PathNode,
GorillaCookieStoreSaveTrackingFlow::PathGraph, GorillaSessionOptionsTrackingFlow::PathGraph,
BoolToGorillaSessionOptionsTrackingFlow::PathGraph>;
module MergedFlow =
DataFlow::MergePathGraph3<NetHttpCookieTrackingFlow::PathNode,
BoolToGinSetCookieTrackingFlow::PathNode, GorillaTrackingFlow::PathNode,
NetHttpCookieTrackingFlow::PathGraph, BoolToGinSetCookieTrackingFlow::PathGraph,
GorillaTrackingFlow::PathGraph>;
import MergedFlow::PathGraph
/** Holds if `HttpOnly` of `net/http.SetCookie` is set to `false` or not set (default value is used). */
predicate isNetHttpCookieFlow(
NetHttpCookieTrackingFlow::PathNode source, NetHttpCookieTrackingFlow::PathNode sink
) {
exists(
NameToNetHttpCookieTrackingFlow::PathNode sensitiveName,
NameToNetHttpCookieTrackingFlow::PathNode setCookieSink
|
NameToNetHttpCookieTrackingFlow::flowPath(sensitiveName, setCookieSink) and
(
not BoolToNetHttpCookieTrackingFlow::flowTo(sink.getNode()) and
source.asPathNode1() = sensitiveName and
sink.asPathNode1() = setCookieSink
or
BoolToNetHttpCookieTrackingFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) and
source.getNode().getBoolValue() = false and
setCookieSink.getNode() = sink.getNode()
)
)
}
/**
* Holds if there is gorilla cookie store creation to `Save` path and
* `HttpOnly` is set to `false` or not set (default value is used).
*/
predicate isGorillaSessionsCookieFlow(
GorillaTrackingFlow::PathNode source, GorillaTrackingFlow::PathNode sink
) {
exists(
GorillaCookieStoreSaveTrackingFlow::PathNode cookieStoreCreate,
GorillaCookieStoreSaveTrackingFlow::PathNode sessionSave
|
GorillaCookieStoreSaveTrackingFlow::flowPath(cookieStoreCreate, sessionSave) and
(
not GorillaSessionOptionsTrackingFlow::flowTo(sink.getNode()) and
source.asPathNode1() = cookieStoreCreate and
sink.asPathNode1() = sessionSave
or
exists(GorillaTrackingFlow::PathNode options, GorillaTrackingFlow::PathNode sessionSave2 |
GorillaSessionOptionsTrackingFlow::flowPath(options.asPathNode2(),
sessionSave2.asPathNode2()) and
(
not BoolToGorillaSessionOptionsTrackingFlow::flowTo(sink.getNode()) and
sink = sessionSave2 and
source = options and
sessionSave.getNode() = sessionSave2.getNode()
or
BoolToGorillaSessionOptionsTrackingFlow::flowPath(source.asPathNode3(), sink.asPathNode3()) and
source.getNode().getBoolValue() = false and
sink.getNode() = sessionSave.getNode()
)
)
)
)
}
from MergedFlow::PathNode source, MergedFlow::PathNode sink
where
isNetHttpCookieFlow(source.asPathNode1(), sink.asPathNode1()) or
BoolToGinSetCookieTrackingFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) or
isGorillaSessionsCookieFlow(source.asPathNode3(), sink.asPathNode3())
select sink.getNode(), source, sink, "Cookie attribute 'HttpOnly' is not set to true."

View File

@@ -1,17 +0,0 @@
package main
import (
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
http.SetCookie(w, &c)
}
func main() {
http.HandleFunc("/", handler)
}

View File

@@ -1,18 +0,0 @@
package main
import (
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: true,
}
http.SetCookie(w, &c)
}
func main() {
http.HandleFunc("/", handler)
}

View File

@@ -1,432 +0,0 @@
edges
| CookieWithoutHttpOnly.go:11:7:14:2 | struct literal | CookieWithoutHttpOnly.go:15:20:15:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:11:7:14:2 | struct literal | CookieWithoutHttpOnly.go:15:21:15:21 | c | provenance | |
| CookieWithoutHttpOnly.go:12:10:12:18 | "session" | CookieWithoutHttpOnly.go:11:7:14:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] | CookieWithoutHttpOnly.go:15:20:15:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:15:21:15:21 | c | CookieWithoutHttpOnly.go:15:20:15:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:15:21:15:21 | c | CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | CookieWithoutHttpOnly.go:24:20:24:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | CookieWithoutHttpOnly.go:24:20:24:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | CookieWithoutHttpOnly.go:24:21:24:21 | c | provenance | |
| CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | CookieWithoutHttpOnly.go:24:21:24:21 | c | provenance | |
| CookieWithoutHttpOnly.go:20:13:20:21 | "session" | CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:22:13:22:17 | false | CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | CookieWithoutHttpOnly.go:24:20:24:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | CookieWithoutHttpOnly.go:24:20:24:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:24:21:24:21 | c | CookieWithoutHttpOnly.go:24:20:24:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:24:21:24:21 | c | CookieWithoutHttpOnly.go:24:20:24:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:24:21:24:21 | c | CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:24:21:24:21 | c | CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | CookieWithoutHttpOnly.go:33:20:33:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | CookieWithoutHttpOnly.go:33:20:33:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | CookieWithoutHttpOnly.go:33:21:33:21 | c | provenance | |
| CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | CookieWithoutHttpOnly.go:33:21:33:21 | c | provenance | |
| CookieWithoutHttpOnly.go:29:13:29:21 | "session" | CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:31:13:31:16 | true | CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | CookieWithoutHttpOnly.go:33:20:33:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | CookieWithoutHttpOnly.go:33:20:33:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:33:21:33:21 | c | CookieWithoutHttpOnly.go:33:20:33:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:33:21:33:21 | c | CookieWithoutHttpOnly.go:33:20:33:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:33:21:33:21 | c | CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:33:21:33:21 | c | CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | CookieWithoutHttpOnly.go:42:20:42:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | CookieWithoutHttpOnly.go:42:20:42:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | CookieWithoutHttpOnly.go:42:21:42:21 | c | provenance | |
| CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | CookieWithoutHttpOnly.go:42:21:42:21 | c | provenance | |
| CookieWithoutHttpOnly.go:38:10:38:18 | "session" | CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:41:15:41:18 | true | CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | CookieWithoutHttpOnly.go:42:20:42:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | CookieWithoutHttpOnly.go:42:20:42:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:42:21:42:21 | c | CookieWithoutHttpOnly.go:42:20:42:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:42:21:42:21 | c | CookieWithoutHttpOnly.go:42:20:42:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:42:21:42:21 | c | CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:42:21:42:21 | c | CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | CookieWithoutHttpOnly.go:51:20:51:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | CookieWithoutHttpOnly.go:51:20:51:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | CookieWithoutHttpOnly.go:51:21:51:21 | c | provenance | |
| CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | CookieWithoutHttpOnly.go:51:21:51:21 | c | provenance | |
| CookieWithoutHttpOnly.go:47:10:47:18 | "session" | CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:50:15:50:19 | false | CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | CookieWithoutHttpOnly.go:51:20:51:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | CookieWithoutHttpOnly.go:51:20:51:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:51:21:51:21 | c | CookieWithoutHttpOnly.go:51:20:51:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:51:21:51:21 | c | CookieWithoutHttpOnly.go:51:20:51:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:51:21:51:21 | c | CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:51:21:51:21 | c | CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:55:2:55:4 | definition of val | CookieWithoutHttpOnly.go:59:13:59:15 | val | provenance | |
| CookieWithoutHttpOnly.go:55:9:55:13 | false | CookieWithoutHttpOnly.go:59:13:59:15 | val | provenance | |
| CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | CookieWithoutHttpOnly.go:61:20:61:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | CookieWithoutHttpOnly.go:61:20:61:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | CookieWithoutHttpOnly.go:61:21:61:21 | c | provenance | |
| CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | CookieWithoutHttpOnly.go:61:21:61:21 | c | provenance | |
| CookieWithoutHttpOnly.go:57:13:57:21 | "session" | CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:59:13:59:15 | val | CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | CookieWithoutHttpOnly.go:61:20:61:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | CookieWithoutHttpOnly.go:61:20:61:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:61:21:61:21 | c | CookieWithoutHttpOnly.go:61:20:61:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:61:21:61:21 | c | CookieWithoutHttpOnly.go:61:20:61:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:61:21:61:21 | c | CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:61:21:61:21 | c | CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:65:2:65:4 | definition of val | CookieWithoutHttpOnly.go:69:13:69:15 | val | provenance | |
| CookieWithoutHttpOnly.go:65:9:65:12 | true | CookieWithoutHttpOnly.go:69:13:69:15 | val | provenance | |
| CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | CookieWithoutHttpOnly.go:71:20:71:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | CookieWithoutHttpOnly.go:71:20:71:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | CookieWithoutHttpOnly.go:71:21:71:21 | c | provenance | |
| CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | CookieWithoutHttpOnly.go:71:21:71:21 | c | provenance | |
| CookieWithoutHttpOnly.go:67:13:67:21 | "session" | CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:69:13:69:15 | val | CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | CookieWithoutHttpOnly.go:71:20:71:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | CookieWithoutHttpOnly.go:71:20:71:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:71:21:71:21 | c | CookieWithoutHttpOnly.go:71:20:71:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:71:21:71:21 | c | CookieWithoutHttpOnly.go:71:20:71:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:71:21:71:21 | c | CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:71:21:71:21 | c | CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:75:2:75:4 | definition of val | CookieWithoutHttpOnly.go:80:15:80:17 | val | provenance | |
| CookieWithoutHttpOnly.go:75:9:75:12 | true | CookieWithoutHttpOnly.go:80:15:80:17 | val | provenance | |
| CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | CookieWithoutHttpOnly.go:81:20:81:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | CookieWithoutHttpOnly.go:81:20:81:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | CookieWithoutHttpOnly.go:81:21:81:21 | c | provenance | |
| CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | CookieWithoutHttpOnly.go:81:21:81:21 | c | provenance | |
| CookieWithoutHttpOnly.go:77:10:77:18 | "session" | CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:80:15:80:17 | val | CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | CookieWithoutHttpOnly.go:81:20:81:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | CookieWithoutHttpOnly.go:81:20:81:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:81:21:81:21 | c | CookieWithoutHttpOnly.go:81:20:81:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:81:21:81:21 | c | CookieWithoutHttpOnly.go:81:20:81:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:81:21:81:21 | c | CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:81:21:81:21 | c | CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:85:2:85:4 | definition of val | CookieWithoutHttpOnly.go:90:15:90:17 | val | provenance | |
| CookieWithoutHttpOnly.go:85:9:85:13 | false | CookieWithoutHttpOnly.go:90:15:90:17 | val | provenance | |
| CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | CookieWithoutHttpOnly.go:91:20:91:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | CookieWithoutHttpOnly.go:91:20:91:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | CookieWithoutHttpOnly.go:91:21:91:21 | c | provenance | |
| CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | CookieWithoutHttpOnly.go:91:21:91:21 | c | provenance | |
| CookieWithoutHttpOnly.go:87:10:87:18 | "session" | CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:90:15:90:17 | val | CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | CookieWithoutHttpOnly.go:91:20:91:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | CookieWithoutHttpOnly.go:91:20:91:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:91:21:91:21 | c | CookieWithoutHttpOnly.go:91:20:91:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:91:21:91:21 | c | CookieWithoutHttpOnly.go:91:20:91:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:91:21:91:21 | c | CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:91:21:91:21 | c | CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:95:7:98:2 | struct literal | CookieWithoutHttpOnly.go:100:20:100:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:95:7:98:2 | struct literal | CookieWithoutHttpOnly.go:100:21:100:21 | c | provenance | |
| CookieWithoutHttpOnly.go:99:15:99:19 | false | CookieWithoutHttpOnly.go:95:7:98:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] | CookieWithoutHttpOnly.go:100:20:100:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:100:21:100:21 | c | CookieWithoutHttpOnly.go:100:20:100:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:100:21:100:21 | c | CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:104:10:104:18 | "session" | CookieWithoutHttpOnly.go:106:10:106:13 | name | provenance | |
| CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | CookieWithoutHttpOnly.go:110:20:110:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | CookieWithoutHttpOnly.go:110:20:110:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | CookieWithoutHttpOnly.go:110:21:110:21 | c | provenance | |
| CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | CookieWithoutHttpOnly.go:110:21:110:21 | c | provenance | |
| CookieWithoutHttpOnly.go:106:10:106:13 | name | CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:109:15:109:19 | false | CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | CookieWithoutHttpOnly.go:110:20:110:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | CookieWithoutHttpOnly.go:110:20:110:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:110:21:110:21 | c | CookieWithoutHttpOnly.go:110:20:110:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:110:21:110:21 | c | CookieWithoutHttpOnly.go:110:20:110:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:110:21:110:21 | c | CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:110:21:110:21 | c | CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:114:13:114:24 | "login_name" | CookieWithoutHttpOnly.go:116:10:116:16 | session | provenance | |
| CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | CookieWithoutHttpOnly.go:120:20:120:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | CookieWithoutHttpOnly.go:120:20:120:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | CookieWithoutHttpOnly.go:120:21:120:21 | c | provenance | |
| CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | CookieWithoutHttpOnly.go:120:21:120:21 | c | provenance | |
| CookieWithoutHttpOnly.go:116:10:116:16 | session | CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:119:15:119:19 | false | CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | CookieWithoutHttpOnly.go:120:20:120:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | CookieWithoutHttpOnly.go:120:20:120:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:120:21:120:21 | c | CookieWithoutHttpOnly.go:120:20:120:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:120:21:120:21 | c | CookieWithoutHttpOnly.go:120:20:120:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:120:21:120:21 | c | CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:120:21:120:21 | c | CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:126:16:126:20 | store | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:134:16:134:20 | store | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:146:16:146:20 | store | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:158:16:158:20 | store | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:170:16:170:20 | store | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:183:16:183:20 | store | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:195:16:195:20 | store | provenance | |
| CookieWithoutHttpOnly.go:126:2:126:43 | ... := ...[0] | CookieWithoutHttpOnly.go:129:2:129:8 | session | provenance | |
| CookieWithoutHttpOnly.go:126:16:126:20 | store | CookieWithoutHttpOnly.go:126:2:126:43 | ... := ...[0] | provenance | Config |
| CookieWithoutHttpOnly.go:133:2:133:9 | definition of httpOnly | CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly | provenance | |
| CookieWithoutHttpOnly.go:133:14:133:18 | false | CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly | provenance | |
| CookieWithoutHttpOnly.go:134:2:134:43 | ... := ...[0] | CookieWithoutHttpOnly.go:142:2:142:8 | session | provenance | |
| CookieWithoutHttpOnly.go:134:16:134:20 | store | CookieWithoutHttpOnly.go:134:2:134:43 | ... := ...[0] | provenance | Config |
| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | CookieWithoutHttpOnly.go:142:2:142:8 | session | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | CookieWithoutHttpOnly.go:142:2:142:8 | session | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:142:2:142:8 | session | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:142:2:142:8 | session | provenance | |
| CookieWithoutHttpOnly.go:137:20:140:2 | &... | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:137:20:140:2 | &... | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:137:20:140:2 | &... | CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:137:20:140:2 | &... | CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | CookieWithoutHttpOnly.go:137:20:140:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | CookieWithoutHttpOnly.go:137:20:140:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly | CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:146:2:146:43 | ... := ...[0] | CookieWithoutHttpOnly.go:153:2:153:8 | session | provenance | |
| CookieWithoutHttpOnly.go:146:16:146:20 | store | CookieWithoutHttpOnly.go:146:2:146:43 | ... := ...[0] | provenance | Config |
| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] | CookieWithoutHttpOnly.go:153:2:153:8 | session | provenance | |
| CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:153:2:153:8 | session | provenance | |
| CookieWithoutHttpOnly.go:149:20:151:2 | &... | CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:149:20:151:2 | &... | CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:149:21:151:2 | struct literal | CookieWithoutHttpOnly.go:149:20:151:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:157:2:157:9 | definition of httpOnly | CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly | provenance | |
| CookieWithoutHttpOnly.go:157:14:157:17 | true | CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly | provenance | |
| CookieWithoutHttpOnly.go:158:2:158:43 | ... := ...[0] | CookieWithoutHttpOnly.go:166:2:166:8 | session | provenance | |
| CookieWithoutHttpOnly.go:158:16:158:20 | store | CookieWithoutHttpOnly.go:158:2:158:43 | ... := ...[0] | provenance | Config |
| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | CookieWithoutHttpOnly.go:166:2:166:8 | session | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | CookieWithoutHttpOnly.go:166:2:166:8 | session | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:166:2:166:8 | session | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:166:2:166:8 | session | provenance | |
| CookieWithoutHttpOnly.go:161:20:164:2 | &... | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:161:20:164:2 | &... | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:161:20:164:2 | &... | CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:161:20:164:2 | &... | CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | CookieWithoutHttpOnly.go:161:20:164:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | CookieWithoutHttpOnly.go:161:20:164:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly | CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:169:56:169:63 | argument corresponding to httpOnly | CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly | provenance | |
| CookieWithoutHttpOnly.go:169:56:169:63 | definition of httpOnly | CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly | provenance | |
| CookieWithoutHttpOnly.go:170:2:170:43 | ... := ...[0] | CookieWithoutHttpOnly.go:178:2:178:8 | session | provenance | |
| CookieWithoutHttpOnly.go:170:16:170:20 | store | CookieWithoutHttpOnly.go:170:2:170:43 | ... := ...[0] | provenance | Config |
| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | CookieWithoutHttpOnly.go:178:2:178:8 | session | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | CookieWithoutHttpOnly.go:178:2:178:8 | session | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:178:2:178:8 | session | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:178:2:178:8 | session | provenance | |
| CookieWithoutHttpOnly.go:173:20:176:2 | &... | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:173:20:176:2 | &... | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:173:20:176:2 | &... | CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:173:20:176:2 | &... | CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | CookieWithoutHttpOnly.go:173:20:176:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | CookieWithoutHttpOnly.go:173:20:176:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly | CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:183:2:183:43 | ... := ...[0] | CookieWithoutHttpOnly.go:191:19:191:25 | session | provenance | |
| CookieWithoutHttpOnly.go:183:16:183:20 | store | CookieWithoutHttpOnly.go:183:2:183:43 | ... := ...[0] | provenance | Config |
| CookieWithoutHttpOnly.go:195:2:195:43 | ... := ...[0] | CookieWithoutHttpOnly.go:202:19:202:25 | session | provenance | |
| CookieWithoutHttpOnly.go:195:16:195:20 | store | CookieWithoutHttpOnly.go:195:2:195:43 | ... := ...[0] | provenance | Config |
nodes
| CookieWithoutHttpOnly.go:11:7:14:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:12:10:12:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:15:20:15:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:15:21:15:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:20:13:20:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:22:13:22:17 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:24:21:24:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:24:21:24:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:29:13:29:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:31:13:31:16 | true | semmle.label | true |
| CookieWithoutHttpOnly.go:33:20:33:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:33:20:33:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:33:21:33:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:33:21:33:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:38:10:38:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:41:15:41:18 | true | semmle.label | true |
| CookieWithoutHttpOnly.go:42:20:42:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:42:20:42:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:42:21:42:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:42:21:42:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:47:10:47:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:50:15:50:19 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:51:21:51:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:51:21:51:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:55:2:55:4 | definition of val | semmle.label | definition of val |
| CookieWithoutHttpOnly.go:55:9:55:13 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:57:13:57:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:59:13:59:15 | val | semmle.label | val |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:61:21:61:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:61:21:61:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:65:2:65:4 | definition of val | semmle.label | definition of val |
| CookieWithoutHttpOnly.go:65:9:65:12 | true | semmle.label | true |
| CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:67:13:67:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:69:13:69:15 | val | semmle.label | val |
| CookieWithoutHttpOnly.go:71:20:71:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:71:20:71:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:71:21:71:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:71:21:71:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:75:2:75:4 | definition of val | semmle.label | definition of val |
| CookieWithoutHttpOnly.go:75:9:75:12 | true | semmle.label | true |
| CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:77:10:77:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:80:15:80:17 | val | semmle.label | val |
| CookieWithoutHttpOnly.go:81:20:81:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:81:20:81:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:81:21:81:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:81:21:81:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:85:2:85:4 | definition of val | semmle.label | definition of val |
| CookieWithoutHttpOnly.go:85:9:85:13 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:87:10:87:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:90:15:90:17 | val | semmle.label | val |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:91:21:91:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:91:21:91:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:95:7:98:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:99:15:99:19 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:100:20:100:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:100:21:100:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:104:10:104:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:106:10:106:13 | name | semmle.label | name |
| CookieWithoutHttpOnly.go:109:15:109:19 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:110:21:110:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:110:21:110:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:114:13:114:24 | "login_name" | semmle.label | "login_name" |
| CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:116:10:116:16 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:119:15:119:19 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:120:21:120:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:120:21:120:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | semmle.label | call to NewCookieStore |
| CookieWithoutHttpOnly.go:126:2:126:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:126:16:126:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:129:2:129:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:133:2:133:9 | definition of httpOnly | semmle.label | definition of httpOnly |
| CookieWithoutHttpOnly.go:133:14:133:18 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:134:2:134:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:134:16:134:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:137:20:140:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:137:20:140:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly | semmle.label | httpOnly |
| CookieWithoutHttpOnly.go:142:2:142:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:142:2:142:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:142:2:142:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:146:2:146:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:146:16:146:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:149:20:151:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:149:21:151:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:153:2:153:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:153:2:153:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:157:2:157:9 | definition of httpOnly | semmle.label | definition of httpOnly |
| CookieWithoutHttpOnly.go:157:14:157:17 | true | semmle.label | true |
| CookieWithoutHttpOnly.go:158:2:158:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:158:16:158:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:161:20:164:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:161:20:164:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly | semmle.label | httpOnly |
| CookieWithoutHttpOnly.go:166:2:166:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:166:2:166:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:166:2:166:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:169:56:169:63 | argument corresponding to httpOnly | semmle.label | argument corresponding to httpOnly |
| CookieWithoutHttpOnly.go:169:56:169:63 | definition of httpOnly | semmle.label | definition of httpOnly |
| CookieWithoutHttpOnly.go:170:2:170:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:170:16:170:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:173:20:176:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:173:20:176:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly | semmle.label | httpOnly |
| CookieWithoutHttpOnly.go:178:2:178:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:178:2:178:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:178:2:178:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:183:2:183:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:183:16:183:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:191:19:191:25 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:195:2:195:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:195:16:195:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:202:19:202:25 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:214:66:214:70 | false | semmle.label | false |
subpaths
#select
| CookieWithoutHttpOnly.go:15:20:15:21 | &... | CookieWithoutHttpOnly.go:12:10:12:18 | "session" | CookieWithoutHttpOnly.go:15:20:15:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... | CookieWithoutHttpOnly.go:22:13:22:17 | false | CookieWithoutHttpOnly.go:24:20:24:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... | CookieWithoutHttpOnly.go:50:15:50:19 | false | CookieWithoutHttpOnly.go:51:20:51:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... | CookieWithoutHttpOnly.go:55:9:55:13 | false | CookieWithoutHttpOnly.go:61:20:61:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... | CookieWithoutHttpOnly.go:85:9:85:13 | false | CookieWithoutHttpOnly.go:91:20:91:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... | CookieWithoutHttpOnly.go:109:15:109:19 | false | CookieWithoutHttpOnly.go:110:20:110:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... | CookieWithoutHttpOnly.go:119:15:119:19 | false | CookieWithoutHttpOnly.go:120:20:120:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:129:2:129:8 | session | CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:129:2:129:8 | session | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:142:2:142:8 | session | CookieWithoutHttpOnly.go:133:14:133:18 | false | CookieWithoutHttpOnly.go:142:2:142:8 | session | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:153:2:153:8 | session | CookieWithoutHttpOnly.go:149:21:151:2 | struct literal | CookieWithoutHttpOnly.go:153:2:153:8 | session | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:191:19:191:25 | session | CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:191:19:191:25 | session | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:202:19:202:25 | session | CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:202:19:202:25 | session | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:214:66:214:70 | false | CookieWithoutHttpOnly.go:214:66:214:70 | false | CookieWithoutHttpOnly.go:214:66:214:70 | false | Cookie attribute 'HttpOnly' is not set to true. |

View File

@@ -1,219 +0,0 @@
package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/gorilla/sessions"
)
func handler1(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
http.SetCookie(w, &c) // BAD: HttpOnly set to false by default
}
func handler2(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: false,
}
http.SetCookie(w, &c) // BAD: HttpOnly explicitly set to false
}
func handler3(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: true,
}
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler4(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = true
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler5(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // BAD: HttpOnly explicitly set to false
}
func handler6(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: val,
}
http.SetCookie(w, &c) // BAD: HttpOnly explicitly set to false
}
func handler7(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: val,
}
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler8(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = val
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler9(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = val
http.SetCookie(w, &c) // BAD: HttpOnly explicitly set to false
}
func handler10(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "consent",
Value: "1",
}
c.HttpOnly = false
http.SetCookie(w, &c) // GOOD: Name is not auth related
}
func handler11(w http.ResponseWriter, r *http.Request) {
name := "session"
c := http.Cookie{
Name: name,
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // BAD: auth related name
}
func handler12(w http.ResponseWriter, r *http.Request) {
session := "login_name"
c := http.Cookie{
Name: session,
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // BAD: auth related name
}
var store = sessions.NewCookieStore([]byte("aa"))
func handler13(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Save(r, w) // BAD: Default options are set (false)
}
func handler14(w http.ResponseWriter, r *http.Request) {
httpOnly := false
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
HttpOnly: httpOnly,
}
session.Save(r, w) // BAD: Explicitly set to false
}
func handler15(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
}
session.Save(r, w) // BAD: default (false) is used
}
func handler16(w http.ResponseWriter, r *http.Request) {
httpOnly := true
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
HttpOnly: httpOnly,
}
session.Save(r, w) // GOOD: value is true
}
func handler17(w http.ResponseWriter, r *http.Request, httpOnly bool) {
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
HttpOnly: httpOnly,
}
session.Save(r, w) // GOOD: value is unknown
}
func handler18(w http.ResponseWriter, r *http.Request) {
httpOnly := false
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
HttpOnly: httpOnly,
}
store.Save(r, w, session) // BAD: Explicitly set to false
}
func handler19(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
}
store.Save(r, w, session) // BAD: default (false) is used
}
func main() {
router := gin.Default()
router.GET("/cookie", func(c *gin.Context) {
_, err := c.Cookie("session")
if err != nil {
c.SetCookie("session", "test", 3600, "/", "localhost", false, false) // BAD: httpOnly set to false
}
})
router.Run()
}

View File

@@ -1 +0,0 @@
experimental/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1,75 +0,0 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/gorilla/sessions, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/gorilla/sessions (exports: CookieStore; functions: NewCookieStore)
// Package sessions is a stub of github.com/gorilla/sessions, generated by depstubber.
package sessions
import (
http "net/http"
)
type CookieStore struct {
Codecs []interface{}
Options *Options
}
func (_ *CookieStore) Get(_ *http.Request, _ string) (*Session, error) {
return nil, nil
}
func (_ *CookieStore) MaxAge(_ int) {}
func (_ *CookieStore) New(_ *http.Request, _ string) (*Session, error) {
return nil, nil
}
func (_ *CookieStore) Save(_ *http.Request, _ http.ResponseWriter, _ *Session) error {
return nil
}
func NewCookieStore(_ ...[]byte) *CookieStore {
return nil
}
type Options struct {
Path string
Domain string
MaxAge int
Secure bool
HttpOnly bool
SameSite http.SameSite
}
type Session struct {
ID string
Values map[interface{}]interface{}
Options *Options
IsNew bool
}
func (_ *Session) AddFlash(_ interface{}, _ ...string) {}
func (_ *Session) Flashes(_ ...string) []interface{} {
return nil
}
func (_ *Session) Name() string {
return ""
}
func (_ *Session) Save(_ *http.Request, _ http.ResponseWriter) error {
return nil
}
func (_ *Session) Store() Store {
return nil
}
type Store interface {
Get(_ *http.Request, _ string) (*Session, error)
New(_ *http.Request, _ string) (*Session, error)
Save(_ *http.Request, _ http.ResponseWriter, _ *Session) error
}

View File

@@ -1,6 +0,0 @@
# github.com/gin-gonic/gin v1.7.1
## explicit
github.com/gin-gonic/gin
# github.com/gorilla/sessions v1.2.1
## explicit
github.com/gorilla/sessions

View File

@@ -0,0 +1,139 @@
#select
| CookieWithoutHttpOnly.go:14:2:14:22 | call to SetCookie | CookieWithoutHttpOnly.go:11:10:11:18 | "session" | CookieWithoutHttpOnly.go:14:20:14:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:11:10:11:18 | "session" | session |
| CookieWithoutHttpOnly.go:23:2:23:22 | call to SetCookie | CookieWithoutHttpOnly.go:19:13:19:21 | "session" | CookieWithoutHttpOnly.go:23:20:23:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:19:13:19:21 | "session" | session |
| CookieWithoutHttpOnly.go:50:2:50:22 | call to SetCookie | CookieWithoutHttpOnly.go:46:10:46:18 | "session" | CookieWithoutHttpOnly.go:50:20:50:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:46:10:46:18 | "session" | session |
| CookieWithoutHttpOnly.go:60:2:60:22 | call to SetCookie | CookieWithoutHttpOnly.go:56:13:56:21 | "session" | CookieWithoutHttpOnly.go:60:20:60:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:56:13:56:21 | "session" | session |
| CookieWithoutHttpOnly.go:90:2:90:22 | call to SetCookie | CookieWithoutHttpOnly.go:86:10:86:18 | "session" | CookieWithoutHttpOnly.go:90:20:90:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:86:10:86:18 | "session" | session |
| CookieWithoutHttpOnly.go:109:2:109:22 | call to SetCookie | CookieWithoutHttpOnly.go:103:10:103:18 | "session" | CookieWithoutHttpOnly.go:109:20:109:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:103:10:103:18 | "session" | session |
| CookieWithoutHttpOnly.go:119:2:119:22 | call to SetCookie | CookieWithoutHttpOnly.go:113:13:113:24 | "login_name" | CookieWithoutHttpOnly.go:119:20:119:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:113:13:113:24 | "login_name" | login_name |
| CookieWithoutHttpOnly.go:119:2:119:22 | call to SetCookie | CookieWithoutHttpOnly.go:115:10:115:16 | session | CookieWithoutHttpOnly.go:119:20:119:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:115:10:115:16 | session | session |
| CookieWithoutHttpOnly.go:131:4:131:71 | call to SetCookie | CookieWithoutHttpOnly.go:131:16:131:24 | "session" | CookieWithoutHttpOnly.go:131:16:131:24 | "session" | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:131:16:131:24 | "session" | session |
edges
| CookieWithoutHttpOnly.go:10:7:13:2 | struct literal | CookieWithoutHttpOnly.go:14:20:14:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:10:7:13:2 | struct literal | CookieWithoutHttpOnly.go:14:21:14:21 | c | provenance | |
| CookieWithoutHttpOnly.go:11:10:11:18 | "session" | CookieWithoutHttpOnly.go:10:7:13:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:14:20:14:21 | &... [pointer] | CookieWithoutHttpOnly.go:14:20:14:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:14:21:14:21 | c | CookieWithoutHttpOnly.go:14:20:14:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:14:21:14:21 | c | CookieWithoutHttpOnly.go:14:20:14:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:18:7:22:2 | struct literal | CookieWithoutHttpOnly.go:23:20:23:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:18:7:22:2 | struct literal | CookieWithoutHttpOnly.go:23:21:23:21 | c | provenance | |
| CookieWithoutHttpOnly.go:19:13:19:21 | "session" | CookieWithoutHttpOnly.go:18:7:22:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:23:20:23:21 | &... [pointer] | CookieWithoutHttpOnly.go:23:20:23:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:23:21:23:21 | c | CookieWithoutHttpOnly.go:23:20:23:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:23:21:23:21 | c | CookieWithoutHttpOnly.go:23:20:23:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:27:7:31:2 | struct literal | CookieWithoutHttpOnly.go:32:20:32:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:27:7:31:2 | struct literal | CookieWithoutHttpOnly.go:32:21:32:21 | c | provenance | |
| CookieWithoutHttpOnly.go:28:13:28:21 | "session" | CookieWithoutHttpOnly.go:27:7:31:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:32:20:32:21 | &... [pointer] | CookieWithoutHttpOnly.go:32:20:32:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:32:21:32:21 | c | CookieWithoutHttpOnly.go:32:20:32:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:32:21:32:21 | c | CookieWithoutHttpOnly.go:32:20:32:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:36:7:39:2 | struct literal | CookieWithoutHttpOnly.go:41:20:41:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:36:7:39:2 | struct literal | CookieWithoutHttpOnly.go:41:21:41:21 | c | provenance | |
| CookieWithoutHttpOnly.go:37:10:37:18 | "session" | CookieWithoutHttpOnly.go:36:7:39:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:41:20:41:21 | &... [pointer] | CookieWithoutHttpOnly.go:41:20:41:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:41:21:41:21 | c | CookieWithoutHttpOnly.go:41:20:41:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:41:21:41:21 | c | CookieWithoutHttpOnly.go:41:20:41:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:45:7:48:2 | struct literal | CookieWithoutHttpOnly.go:50:20:50:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:45:7:48:2 | struct literal | CookieWithoutHttpOnly.go:50:21:50:21 | c | provenance | |
| CookieWithoutHttpOnly.go:46:10:46:18 | "session" | CookieWithoutHttpOnly.go:45:7:48:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:50:20:50:21 | &... [pointer] | CookieWithoutHttpOnly.go:50:20:50:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:50:21:50:21 | c | CookieWithoutHttpOnly.go:50:20:50:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:50:21:50:21 | c | CookieWithoutHttpOnly.go:50:20:50:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:55:7:59:2 | struct literal | CookieWithoutHttpOnly.go:60:20:60:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:55:7:59:2 | struct literal | CookieWithoutHttpOnly.go:60:21:60:21 | c | provenance | |
| CookieWithoutHttpOnly.go:56:13:56:21 | "session" | CookieWithoutHttpOnly.go:55:7:59:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:60:20:60:21 | &... [pointer] | CookieWithoutHttpOnly.go:60:20:60:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:60:21:60:21 | c | CookieWithoutHttpOnly.go:60:20:60:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:60:21:60:21 | c | CookieWithoutHttpOnly.go:60:20:60:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:65:7:69:2 | struct literal | CookieWithoutHttpOnly.go:70:20:70:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:65:7:69:2 | struct literal | CookieWithoutHttpOnly.go:70:21:70:21 | c | provenance | |
| CookieWithoutHttpOnly.go:66:13:66:21 | "session" | CookieWithoutHttpOnly.go:65:7:69:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:70:20:70:21 | &... [pointer] | CookieWithoutHttpOnly.go:70:20:70:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:70:21:70:21 | c | CookieWithoutHttpOnly.go:70:20:70:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:70:21:70:21 | c | CookieWithoutHttpOnly.go:70:20:70:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:75:7:78:2 | struct literal | CookieWithoutHttpOnly.go:80:20:80:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:75:7:78:2 | struct literal | CookieWithoutHttpOnly.go:80:21:80:21 | c | provenance | |
| CookieWithoutHttpOnly.go:76:10:76:18 | "session" | CookieWithoutHttpOnly.go:75:7:78:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:80:20:80:21 | &... [pointer] | CookieWithoutHttpOnly.go:80:20:80:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:80:21:80:21 | c | CookieWithoutHttpOnly.go:80:20:80:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:80:21:80:21 | c | CookieWithoutHttpOnly.go:80:20:80:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:85:7:88:2 | struct literal | CookieWithoutHttpOnly.go:90:20:90:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:85:7:88:2 | struct literal | CookieWithoutHttpOnly.go:90:21:90:21 | c | provenance | |
| CookieWithoutHttpOnly.go:86:10:86:18 | "session" | CookieWithoutHttpOnly.go:85:7:88:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:90:20:90:21 | &... [pointer] | CookieWithoutHttpOnly.go:90:20:90:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:90:21:90:21 | c | CookieWithoutHttpOnly.go:90:20:90:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:90:21:90:21 | c | CookieWithoutHttpOnly.go:90:20:90:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:103:10:103:18 | "session" | CookieWithoutHttpOnly.go:105:10:105:13 | name | provenance | |
| CookieWithoutHttpOnly.go:104:7:107:2 | struct literal | CookieWithoutHttpOnly.go:109:20:109:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:104:7:107:2 | struct literal | CookieWithoutHttpOnly.go:109:21:109:21 | c | provenance | |
| CookieWithoutHttpOnly.go:105:10:105:13 | name | CookieWithoutHttpOnly.go:104:7:107:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:109:20:109:21 | &... [pointer] | CookieWithoutHttpOnly.go:109:20:109:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:109:21:109:21 | c | CookieWithoutHttpOnly.go:109:20:109:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:109:21:109:21 | c | CookieWithoutHttpOnly.go:109:20:109:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:113:13:113:24 | "login_name" | CookieWithoutHttpOnly.go:115:10:115:16 | session | provenance | |
| CookieWithoutHttpOnly.go:114:7:117:2 | struct literal | CookieWithoutHttpOnly.go:119:20:119:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:114:7:117:2 | struct literal | CookieWithoutHttpOnly.go:119:21:119:21 | c | provenance | |
| CookieWithoutHttpOnly.go:115:10:115:16 | session | CookieWithoutHttpOnly.go:114:7:117:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:119:20:119:21 | &... [pointer] | CookieWithoutHttpOnly.go:119:20:119:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:119:21:119:21 | c | CookieWithoutHttpOnly.go:119:20:119:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:119:21:119:21 | c | CookieWithoutHttpOnly.go:119:20:119:21 | &... [pointer] | provenance | |
nodes
| CookieWithoutHttpOnly.go:10:7:13:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:11:10:11:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:14:20:14:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:14:20:14:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:14:21:14:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:18:7:22:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:19:13:19:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:23:20:23:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:23:20:23:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:23:21:23:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:27:7:31:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:28:13:28:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:32:20:32:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:32:20:32:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:32:21:32:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:36:7:39:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:37:10:37:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:41:20:41:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:41:20:41:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:41:21:41:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:45:7:48:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:46:10:46:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:50:20:50:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:50:20:50:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:50:21:50:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:55:7:59:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:56:13:56:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:60:20:60:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:60:20:60:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:60:21:60:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:65:7:69:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:66:13:66:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:70:20:70:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:70:20:70:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:70:21:70:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:75:7:78:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:76:10:76:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:80:20:80:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:80:20:80:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:80:21:80:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:85:7:88:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:86:10:86:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:90:20:90:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:90:20:90:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:90:21:90:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:103:10:103:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:104:7:107:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:105:10:105:13 | name | semmle.label | name |
| CookieWithoutHttpOnly.go:109:20:109:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:109:20:109:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:109:21:109:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:113:13:113:24 | "login_name" | semmle.label | "login_name" |
| CookieWithoutHttpOnly.go:114:7:117:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:115:10:115:16 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:119:20:119:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:119:20:119:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:119:21:119:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:131:16:131:24 | "session" | semmle.label | "session" |
subpaths

View File

@@ -0,0 +1,136 @@
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func handler1(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
}
http.SetCookie(w, &c) // $ Alert // BAD: HttpOnly set to false by default
}
func handler2(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
HttpOnly: false,
}
http.SetCookie(w, &c) // $ Alert // BAD: HttpOnly explicitly set to false
}
func handler3(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: true,
}
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler4(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = true
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler5(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // $ Alert // BAD: HttpOnly explicitly set to false
}
func handler6(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
HttpOnly: val,
}
http.SetCookie(w, &c) // $ Alert // BAD: HttpOnly explicitly set to false
}
func handler7(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: val,
}
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler8(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = val
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler9(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
}
c.HttpOnly = val
http.SetCookie(w, &c) // $ Alert //BAD: HttpOnly explicitly set to false
}
func handler10(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "consent",
Value: "1",
}
c.HttpOnly = false
http.SetCookie(w, &c) // GOOD: Name is not auth related
}
func handler11(w http.ResponseWriter, r *http.Request) {
name := "session" // $ Source
c := http.Cookie{
Name: name,
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // $ Alert // BAD: auth related name
}
func handler12(w http.ResponseWriter, r *http.Request) {
session := "login_name" // $ Source
c := http.Cookie{
Name: session, // $ Source
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // $ Alert // BAD: auth related name
}
func main() {
router := gin.Default()
router.GET("/cookie", func(c *gin.Context) {
_, err := c.Cookie("session")
if err != nil {
c.SetCookie("session", "test", 3600, "/", "localhost", false, false) // $ Alert // BAD: httpOnly set to false
}
})
router.Run()
}

View File

@@ -0,0 +1,2 @@
query: Security/CWE-1004/CookieWithoutHttpOnly.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -4,5 +4,4 @@ go 1.14
require (
github.com/gin-gonic/gin v1.7.1
github.com/gorilla/sessions v1.2.1
)

View File

@@ -0,0 +1,3 @@
# github.com/gin-gonic/gin v1.7.1
## explicit
github.com/gin-gonic/gin

View File

@@ -0,0 +1,6 @@
| CookieWithoutSecure.go:14:2:14:22 | call to SetCookie | Cookie does not set Secure attribute to true. |
| CookieWithoutSecure.go:23:2:23:22 | call to SetCookie | Cookie does not set Secure attribute to true. |
| CookieWithoutSecure.go:50:2:50:22 | call to SetCookie | Cookie does not set Secure attribute to true. |
| CookieWithoutSecure.go:60:2:60:22 | call to SetCookie | Cookie does not set Secure attribute to true. |
| CookieWithoutSecure.go:90:2:90:22 | call to SetCookie | Cookie does not set Secure attribute to true. |
| CookieWithoutSecure.go:102:4:102:71 | call to SetCookie | Cookie does not set Secure attribute to true. |

View File

@@ -0,0 +1,107 @@
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func handler1(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
}
http.SetCookie(w, &c) // $ Alert // BAD: Secure set to false by default
}
func handler2(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
Secure: false,
}
http.SetCookie(w, &c) // $ Alert // BAD: Secure explicitly set to false
}
func handler3(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
Secure: true,
}
http.SetCookie(w, &c) // GOOD: Secure explicitly set to true
}
func handler4(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.Secure = true
http.SetCookie(w, &c) // GOOD: Secure explicitly set to true
}
func handler5(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
}
c.Secure = false
http.SetCookie(w, &c) // $ Alert // BAD: Secure explicitly set to false
}
func handler6(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
Secure: val,
}
http.SetCookie(w, &c) // $ Alert // BAD: Secure explicitly set to false
}
func handler7(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
Secure: val,
}
http.SetCookie(w, &c) // GOOD: Secure explicitly set to true
}
func handler8(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.Secure = val
http.SetCookie(w, &c) // GOOD: Secure explicitly set to true
}
func handler9(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
}
c.Secure = val
http.SetCookie(w, &c) // $ Alert //BAD: Secure explicitly set to false
}
func main() {
router := gin.Default()
router.GET("/cookie", func(c *gin.Context) {
_, err := c.Cookie("session")
if err != nil {
c.SetCookie("session", "test", 3600, "/", "localhost", false, false) // $ Alert // BAD: Secure set to false
}
})
router.Run()
}

View File

@@ -0,0 +1,2 @@
query: Security/CWE-614/CookieWithoutSecure.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -0,0 +1,7 @@
module example.com/m
go 1.14
require (
github.com/gin-gonic/gin v1.7.1
)

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Manuel Martínez-Almeida
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,12 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/gin-gonic/gin/binding, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/gin-gonic/gin/binding (exports: ; functions: YAML)
// Package binding is a stub of github.com/gin-gonic/gin/binding, generated by depstubber.
package binding
import ()
var YAML interface{} = nil

View File

@@ -0,0 +1,677 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/gin-gonic/gin, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/gin-gonic/gin (exports: Context; functions: Default)
// Package gin is a stub of github.com/gin-gonic/gin, generated by depstubber.
package gin
import (
bufio "bufio"
template "html/template"
io "io"
multipart "mime/multipart"
net "net"
http "net/http"
time "time"
)
type Context struct {
Request *http.Request
Writer ResponseWriter
Params Params
Keys map[string]interface{}
Errors interface{}
Accepted []string
}
func (_ *Context) Abort() {}
func (_ *Context) AbortWithError(_ int, _ error) *Error {
return nil
}
func (_ *Context) AbortWithStatus(_ int) {}
func (_ *Context) AbortWithStatusJSON(_ int, _ interface{}) {}
func (_ *Context) AsciiJSON(_ int, _ interface{}) {}
func (_ *Context) Bind(_ interface{}) error {
return nil
}
func (_ *Context) BindHeader(_ interface{}) error {
return nil
}
func (_ *Context) BindJSON(_ interface{}) error {
return nil
}
func (_ *Context) BindQuery(_ interface{}) error {
return nil
}
func (_ *Context) BindUri(_ interface{}) error {
return nil
}
func (_ *Context) BindWith(_ interface{}, _ interface{}) error {
return nil
}
func (_ *Context) BindXML(_ interface{}) error {
return nil
}
func (_ *Context) BindYAML(_ interface{}) error {
return nil
}
func (_ *Context) ClientIP() string {
return ""
}
func (_ *Context) ContentType() string {
return ""
}
func (_ *Context) Cookie(_ string) (string, error) {
return "", nil
}
func (_ *Context) Copy() *Context {
return nil
}
func (_ *Context) Data(_ int, _ string, _ []byte) {}
func (_ *Context) DataFromReader(_ int, _ int64, _ string, _ io.Reader, _ map[string]string) {}
func (_ *Context) Deadline() (time.Time, bool) {
return time.Time{}, false
}
func (_ *Context) DefaultPostForm(_ string, _ string) string {
return ""
}
func (_ *Context) DefaultQuery(_ string, _ string) string {
return ""
}
func (_ *Context) Done() <-chan struct{} {
return nil
}
func (_ *Context) Err() error {
return nil
}
func (_ *Context) Error(_ error) *Error {
return nil
}
func (_ *Context) File(_ string) {}
func (_ *Context) FileAttachment(_ string, _ string) {}
func (_ *Context) FileFromFS(_ string, _ http.FileSystem) {}
func (_ *Context) FormFile(_ string) (*multipart.FileHeader, error) {
return nil, nil
}
func (_ *Context) FullPath() string {
return ""
}
func (_ *Context) Get(_ string) (interface{}, bool) {
return nil, false
}
func (_ *Context) GetBool(_ string) bool {
return false
}
func (_ *Context) GetDuration(_ string) time.Duration {
return 0
}
func (_ *Context) GetFloat64(_ string) float64 {
return 0
}
func (_ *Context) GetHeader(_ string) string {
return ""
}
func (_ *Context) GetInt(_ string) int {
return 0
}
func (_ *Context) GetInt64(_ string) int64 {
return 0
}
func (_ *Context) GetPostForm(_ string) (string, bool) {
return "", false
}
func (_ *Context) GetPostFormArray(_ string) ([]string, bool) {
return nil, false
}
func (_ *Context) GetPostFormMap(_ string) (map[string]string, bool) {
return nil, false
}
func (_ *Context) GetQuery(_ string) (string, bool) {
return "", false
}
func (_ *Context) GetQueryArray(_ string) ([]string, bool) {
return nil, false
}
func (_ *Context) GetQueryMap(_ string) (map[string]string, bool) {
return nil, false
}
func (_ *Context) GetRawData() ([]byte, error) {
return nil, nil
}
func (_ *Context) GetString(_ string) string {
return ""
}
func (_ *Context) GetStringMap(_ string) map[string]interface{} {
return nil
}
func (_ *Context) GetStringMapString(_ string) map[string]string {
return nil
}
func (_ *Context) GetStringMapStringSlice(_ string) map[string][]string {
return nil
}
func (_ *Context) GetStringSlice(_ string) []string {
return nil
}
func (_ *Context) GetTime(_ string) time.Time {
return time.Time{}
}
func (_ *Context) GetUint(_ string) uint {
return 0
}
func (_ *Context) GetUint64(_ string) uint64 {
return 0
}
func (_ *Context) HTML(_ int, _ string, _ interface{}) {}
func (_ *Context) Handler() HandlerFunc {
return nil
}
func (_ *Context) HandlerName() string {
return ""
}
func (_ *Context) HandlerNames() []string {
return nil
}
func (_ *Context) Header(_ string, _ string) {}
func (_ *Context) IndentedJSON(_ int, _ interface{}) {}
func (_ *Context) IsAborted() bool {
return false
}
func (_ *Context) IsWebsocket() bool {
return false
}
func (_ *Context) JSON(_ int, _ interface{}) {}
func (_ *Context) JSONP(_ int, _ interface{}) {}
func (_ *Context) MultipartForm() (*multipart.Form, error) {
return nil, nil
}
func (_ *Context) MustBindWith(_ interface{}, _ interface{}) error {
return nil
}
func (_ *Context) MustGet(_ string) interface{} {
return nil
}
func (_ *Context) Negotiate(_ int, _ Negotiate) {}
func (_ *Context) NegotiateFormat(_ ...string) string {
return ""
}
func (_ *Context) Next() {}
func (_ *Context) Param(_ string) string {
return ""
}
func (_ *Context) PostForm(_ string) string {
return ""
}
func (_ *Context) PostFormArray(_ string) []string {
return nil
}
func (_ *Context) PostFormMap(_ string) map[string]string {
return nil
}
func (_ *Context) ProtoBuf(_ int, _ interface{}) {}
func (_ *Context) PureJSON(_ int, _ interface{}) {}
func (_ *Context) Query(_ string) string {
return ""
}
func (_ *Context) QueryArray(_ string) []string {
return nil
}
func (_ *Context) QueryMap(_ string) map[string]string {
return nil
}
func (_ *Context) Redirect(_ int, _ string) {}
func (_ *Context) RemoteIP() (net.IP, bool) {
return nil, false
}
func (_ *Context) Render(_ int, _ interface{}) {}
func (_ *Context) SSEvent(_ string, _ interface{}) {}
func (_ *Context) SaveUploadedFile(_ *multipart.FileHeader, _ string) error {
return nil
}
func (_ *Context) SecureJSON(_ int, _ interface{}) {}
func (_ *Context) Set(_ string, _ interface{}) {}
func (_ *Context) SetAccepted(_ ...string) {}
func (_ *Context) SetCookie(_ string, _ string, _ int, _ string, _ string, _ bool, _ bool) {}
func (_ *Context) SetSameSite(_ http.SameSite) {}
func (_ *Context) ShouldBind(_ interface{}) error {
return nil
}
func (_ *Context) ShouldBindBodyWith(_ interface{}, _ interface{}) error {
return nil
}
func (_ *Context) ShouldBindHeader(_ interface{}) error {
return nil
}
func (_ *Context) ShouldBindJSON(_ interface{}) error {
return nil
}
func (_ *Context) ShouldBindQuery(_ interface{}) error {
return nil
}
func (_ *Context) ShouldBindUri(_ interface{}) error {
return nil
}
func (_ *Context) ShouldBindWith(_ interface{}, _ interface{}) error {
return nil
}
func (_ *Context) ShouldBindXML(_ interface{}) error {
return nil
}
func (_ *Context) ShouldBindYAML(_ interface{}) error {
return nil
}
func (_ *Context) Status(_ int) {}
func (_ *Context) Stream(_ func(io.Writer) bool) bool {
return false
}
func (_ *Context) String(_ int, _ string, _ ...interface{}) {}
func (_ *Context) Value(_ interface{}) interface{} {
return nil
}
func (_ *Context) XML(_ int, _ interface{}) {}
func (_ *Context) YAML(_ int, _ interface{}) {}
func Default() *Engine {
return nil
}
type Engine struct {
RouterGroup RouterGroup
RedirectTrailingSlash bool
RedirectFixedPath bool
HandleMethodNotAllowed bool
ForwardedByClientIP bool
RemoteIPHeaders []string
TrustedProxies []string
AppEngine bool
UseRawPath bool
UnescapePathValues bool
MaxMultipartMemory int64
RemoveExtraSlash bool
HTMLRender interface{}
FuncMap template.FuncMap
}
func (_ *Engine) Any(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) BasePath() string {
return ""
}
func (_ *Engine) DELETE(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) Delims(_ string, _ string) *Engine {
return nil
}
func (_ *Engine) GET(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) Group(_ string, _ ...HandlerFunc) *RouterGroup {
return nil
}
func (_ *Engine) HEAD(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) Handle(_ string, _ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) HandleContext(_ *Context) {}
func (_ *Engine) LoadHTMLFiles(_ ...string) {}
func (_ *Engine) LoadHTMLGlob(_ string) {}
func (_ *Engine) NoMethod(_ ...HandlerFunc) {}
func (_ *Engine) NoRoute(_ ...HandlerFunc) {}
func (_ *Engine) OPTIONS(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) PATCH(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) POST(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) PUT(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) Routes() RoutesInfo {
return nil
}
func (_ *Engine) Run(_ ...string) error {
return nil
}
func (_ *Engine) RunFd(_ int) error {
return nil
}
func (_ *Engine) RunListener(_ net.Listener) error {
return nil
}
func (_ *Engine) RunTLS(_ string, _ string, _ string) error {
return nil
}
func (_ *Engine) RunUnix(_ string) error {
return nil
}
func (_ *Engine) SecureJsonPrefix(_ string) *Engine {
return nil
}
func (_ *Engine) ServeHTTP(_ http.ResponseWriter, _ *http.Request) {}
func (_ *Engine) SetFuncMap(_ template.FuncMap) {}
func (_ *Engine) SetHTMLTemplate(_ *template.Template) {}
func (_ *Engine) Static(_ string, _ string) IRoutes {
return nil
}
func (_ *Engine) StaticFS(_ string, _ http.FileSystem) IRoutes {
return nil
}
func (_ *Engine) StaticFile(_ string, _ string) IRoutes {
return nil
}
func (_ *Engine) Use(_ ...HandlerFunc) IRoutes {
return nil
}
type Error struct {
Err error
Type ErrorType
Meta interface{}
}
func (_ Error) Error() string {
return ""
}
func (_ *Error) IsType(_ ErrorType) bool {
return false
}
func (_ *Error) JSON() interface{} {
return nil
}
func (_ *Error) MarshalJSON() ([]byte, error) {
return nil, nil
}
func (_ *Error) SetMeta(_ interface{}) *Error {
return nil
}
func (_ *Error) SetType(_ ErrorType) *Error {
return nil
}
func (_ *Error) Unwrap() error {
return nil
}
type ErrorType uint64
type HandlerFunc func(*Context)
type HandlersChain []HandlerFunc
func (_ HandlersChain) Last() HandlerFunc {
return nil
}
type IRoutes interface {
Any(_ string, _ ...HandlerFunc) IRoutes
DELETE(_ string, _ ...HandlerFunc) IRoutes
GET(_ string, _ ...HandlerFunc) IRoutes
HEAD(_ string, _ ...HandlerFunc) IRoutes
Handle(_ string, _ string, _ ...HandlerFunc) IRoutes
OPTIONS(_ string, _ ...HandlerFunc) IRoutes
PATCH(_ string, _ ...HandlerFunc) IRoutes
POST(_ string, _ ...HandlerFunc) IRoutes
PUT(_ string, _ ...HandlerFunc) IRoutes
Static(_ string, _ string) IRoutes
StaticFS(_ string, _ http.FileSystem) IRoutes
StaticFile(_ string, _ string) IRoutes
Use(_ ...HandlerFunc) IRoutes
}
type Negotiate struct {
Offered []string
HTMLName string
HTMLData interface{}
JSONData interface{}
XMLData interface{}
YAMLData interface{}
Data interface{}
}
type Param struct {
Key string
Value string
}
type Params []Param
func (_ Params) ByName(_ string) string {
return ""
}
func (_ Params) Get(_ string) (string, bool) {
return "", false
}
type ResponseWriter interface {
CloseNotify() <-chan bool
Flush()
Header() http.Header
Hijack() (net.Conn, *bufio.ReadWriter, error)
Pusher() http.Pusher
Size() int
Status() int
Write(_ []byte) (int, error)
WriteHeader(_ int)
WriteHeaderNow()
WriteString(_ string) (int, error)
Written() bool
}
type RouteInfo struct {
Method string
Path string
Handler string
HandlerFunc HandlerFunc
}
type RouterGroup struct {
Handlers HandlersChain
}
func (_ *RouterGroup) Any(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) BasePath() string {
return ""
}
func (_ *RouterGroup) DELETE(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) GET(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) Group(_ string, _ ...HandlerFunc) *RouterGroup {
return nil
}
func (_ *RouterGroup) HEAD(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) Handle(_ string, _ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) OPTIONS(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) PATCH(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) POST(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) PUT(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) Static(_ string, _ string) IRoutes {
return nil
}
func (_ *RouterGroup) StaticFS(_ string, _ http.FileSystem) IRoutes {
return nil
}
func (_ *RouterGroup) StaticFile(_ string, _ string) IRoutes {
return nil
}
func (_ *RouterGroup) Use(_ ...HandlerFunc) IRoutes {
return nil
}
type RoutesInfo []RouteInfo

View File

@@ -0,0 +1,3 @@
# github.com/gin-gonic/gin v1.7.1
## explicit
github.com/gin-gonic/gin

View File

@@ -6,10 +6,14 @@ import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.SensitiveActions
import semmle.code.java.frameworks.android.Compose
private import semmle.code.java.security.Sanitizers
private import semmle.code.java.dataflow.RangeAnalysis
/** A data flow source node for sensitive logging sources. */
abstract class SensitiveLoggerSource extends DataFlow::Node { }
/** A data flow barrier node for sensitive logging sanitizers. */
abstract class SensitiveLoggerBarrier extends DataFlow::Node { }
/** A variable that may hold sensitive information, judging by its name. */
class VariableWithSensitiveName extends Variable {
VariableWithSensitiveName() {
@@ -40,17 +44,89 @@ private class TypeType extends RefType {
}
}
/**
* A sanitizer that may remove sensitive information from a string before logging.
*
* It allows for substring operations taking the first N (or last N, for Kotlin) characters, limited to 7 or fewer.
*/
private class PrefixSuffixBarrier extends SensitiveLoggerBarrier {
PrefixSuffixBarrier() {
exists(MethodCall mc, Method m, int limit |
limit = 7 and
mc.getMethod() = m
|
// substring in Java
(
m.hasQualifiedName("java.lang", "String", "substring") or
m.hasQualifiedName("java.lang", "StringBuffer", "substring") or
m.hasQualifiedName("java.lang", "StringBuilder", "substring")
) and
(
twoArgLimit(mc, limit, false) or
singleArgLimit(mc, limit, false)
) and
this.asExpr() = mc.getQualifier()
or
// Kotlin string operations, which use extension methods (so the string is the first argument)
(
m.hasQualifiedName("kotlin.text", "StringsKt", "substring") and
(
twoArgLimit(mc, limit, true) or
singleArgLimit(mc, limit, true)
)
or
m.hasQualifiedName("kotlin.text", "StringsKt", ["take", "takeLast"]) and
singleArgLimit(mc, limit, true)
) and
this.asExpr() = mc.getArgument(0)
)
}
}
/** A predicate to check single-argument method calls for a constant integer below a set limit. */
bindingset[limit, isKotlin]
private predicate singleArgLimit(MethodCall mc, int limit, boolean isKotlin) {
mc.getNumArgument() = 1 and
exists(int firstArgIndex, int delta |
if isKotlin = true then firstArgIndex = 1 else firstArgIndex = 0
|
bounded(mc.getArgument(firstArgIndex), any(ZeroBound z), delta, true, _) and
delta <= limit
)
}
/** A predicate to check two-argument method calls for zero and a constant integer below a set limit. */
bindingset[limit, isKotlin]
private predicate twoArgLimit(MethodCall mc, int limit, boolean isKotlin) {
mc.getNumArgument() = 2 and
exists(int firstArgIndex, int secondArgIndex, int delta |
isKotlin = true and firstArgIndex = 1 and secondArgIndex = 2
or
isKotlin = false and firstArgIndex = 0 and secondArgIndex = 1
|
// mc.getArgument(firstArgIndex).(CompileTimeConstantExpr).getIntValue() = 0 and
bounded(mc.getArgument(firstArgIndex), any(ZeroBound z), 0, true, _) and
bounded(mc.getArgument(firstArgIndex), any(ZeroBound z), 0, false, _) and
bounded(mc.getArgument(secondArgIndex), any(ZeroBound z), delta, true, _) and
delta <= limit
)
}
private class DefaultSensitiveLoggerBarrier extends SensitiveLoggerBarrier {
DefaultSensitiveLoggerBarrier() {
this.asExpr() instanceof LiveLiteral or
this instanceof SimpleTypeSanitizer or
this.getType() instanceof TypeType
}
}
/** A data-flow configuration for identifying potentially-sensitive data flowing to a log output. */
module SensitiveLoggerConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof SensitiveLoggerSource }
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "log-injection") }
predicate isBarrier(DataFlow::Node sanitizer) {
sanitizer.asExpr() instanceof LiveLiteral or
sanitizer instanceof SimpleTypeSanitizer or
sanitizer.getType() instanceof TypeType
}
predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof SensitiveLoggerBarrier }
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Operations that extract only a fixed-length prefix or suffix of a string (for example, `substring` in Java or `take` in Kotlin), when limited to a length of at most 7 characters, are now treated as sanitizers for the `java/sensitive-log` query.

Some files were not shown because too many files have changed in this diff Show More