mirror of
https://github.com/github/codeql.git
synced 2026-04-23 15:55:18 +02:00
Merge branch 'main' into criemen/pytest-csharp
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Add unique constraint on preprocessor directive and compilation pairs
|
||||
compatibility: backwards
|
||||
@@ -20,6 +20,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
trapFile.WriteSubId(Context.CreateLocation(ReportingLocation));
|
||||
trapFile.WriteSubId(start);
|
||||
trapFile.Write(Symbol.IsActive);
|
||||
trapFile.Write(',');
|
||||
trapFile.Write(Symbol.BranchTaken);
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
trapFile.WriteSubId(Context.CreateLocation(ReportingLocation));
|
||||
trapFile.WriteSubId(start);
|
||||
trapFile.Write(Symbol.IsActive);
|
||||
trapFile.Write(',');
|
||||
trapFile.Write(Symbol.BranchTaken);
|
||||
|
||||
@@ -13,6 +13,14 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
trapFile.WriteSubId(Context.CreateLocation(ReportingLocation));
|
||||
trapFile.WriteSubId(start);
|
||||
trapFile.Write(Symbol.IsActive);
|
||||
trapFile.Write(";trivia");
|
||||
}
|
||||
|
||||
protected override void PopulatePreprocessor(TextWriter trapFile)
|
||||
{
|
||||
trapFile.directive_endifs(this, start);
|
||||
|
||||
@@ -190,37 +190,29 @@ namespace Semmle.Extraction.CSharp
|
||||
var transformedSourcePath = PathTransformer.Transform(sourcePath);
|
||||
|
||||
var trapPath = transformedSourcePath.GetTrapPath(Logger, options.TrapCompression);
|
||||
var upToDate = false;
|
||||
|
||||
// compilation.Clone() is used to allow symbols to be garbage collected.
|
||||
using var trapWriter = transformedSourcePath.CreateTrapWriter(Logger, options.TrapCompression, discardDuplicates: false);
|
||||
|
||||
upToDate = FileIsUpToDate(sourcePath, trapWriter.TrapFile);
|
||||
|
||||
var currentTaskId = IncrementTaskCount();
|
||||
ReportProgressTaskStarted(currentTaskId, sourcePath);
|
||||
|
||||
if (!upToDate)
|
||||
var cx = new Context(ExtractionContext, compilation, trapWriter, new SourceScope(tree), addAssemblyTrapPrefix);
|
||||
// Ensure that the file itself is populated in case the source file is totally empty
|
||||
var root = tree.GetRoot();
|
||||
Entities.File.Create(cx, root.SyntaxTree.FilePath);
|
||||
|
||||
var csNode = (CSharpSyntaxNode)root;
|
||||
var directiveVisitor = new DirectiveVisitor(cx);
|
||||
csNode.Accept(directiveVisitor);
|
||||
foreach (var branch in directiveVisitor.BranchesTaken)
|
||||
{
|
||||
var cx = new Context(ExtractionContext, compilation, trapWriter, new SourceScope(tree), addAssemblyTrapPrefix);
|
||||
// Ensure that the file itself is populated in case the source file is totally empty
|
||||
var root = tree.GetRoot();
|
||||
Entities.File.Create(cx, root.SyntaxTree.FilePath);
|
||||
|
||||
var csNode = (CSharpSyntaxNode)root;
|
||||
var directiveVisitor = new DirectiveVisitor(cx);
|
||||
csNode.Accept(directiveVisitor);
|
||||
foreach (var branch in directiveVisitor.BranchesTaken)
|
||||
{
|
||||
cx.TrapStackSuffix.Add(branch);
|
||||
}
|
||||
csNode.Accept(new CompilationUnitVisitor(cx));
|
||||
cx.PopulateAll();
|
||||
CommentPopulator.ExtractCommentBlocks(cx, cx.CommentGenerator);
|
||||
cx.PopulateAll();
|
||||
cx.TrapStackSuffix.Add(branch);
|
||||
}
|
||||
csNode.Accept(new CompilationUnitVisitor(cx));
|
||||
cx.PopulateAll();
|
||||
CommentPopulator.ExtractCommentBlocks(cx, cx.CommentGenerator);
|
||||
cx.PopulateAll();
|
||||
|
||||
ReportProgressTaskDone(currentTaskId, sourcePath, trapPath, stopwatch.Elapsed, upToDate ? AnalysisAction.UpToDate : AnalysisAction.Extracted);
|
||||
ReportProgressTaskDone(currentTaskId, sourcePath, trapPath, stopwatch.Elapsed, AnalysisAction.Extracted);
|
||||
}
|
||||
catch (Exception ex) // lgtm[cs/catch-of-all-exceptions]
|
||||
{
|
||||
@@ -268,12 +260,6 @@ namespace Semmle.Extraction.CSharp
|
||||
extractionTasks.Add(() => DoAnalyseCompilation());
|
||||
}
|
||||
|
||||
private static bool FileIsUpToDate(string src, string dest)
|
||||
{
|
||||
return File.Exists(dest) &&
|
||||
File.GetLastWriteTime(dest) >= File.GetLastWriteTime(src);
|
||||
}
|
||||
|
||||
private static void AnalyseNamespace(Context cx, INamespaceSymbol ns)
|
||||
{
|
||||
foreach (var memberNamespace in ns.GetNamespaceMembers())
|
||||
|
||||
@@ -194,8 +194,11 @@ namespace Semmle.Extraction
|
||||
var hash = FileUtils.ComputeFileHash(tmpFile);
|
||||
if (existingHash != hash)
|
||||
{
|
||||
var root = TrapFile.Substring(0, TrapFile.Length - 8); // Remove trailing ".trap.gz"
|
||||
if (TryMove(tmpFile, $"{root}-{hash}.trap{TrapExtension(trapCompression)}"))
|
||||
var extension = TrapExtension(trapCompression);
|
||||
var root = TrapFile[..^extension.Length]; // Remove trailing ".trap", ".trap.gz", or ".trap.br"
|
||||
var newTrapName = $"{root}-{hash}{extension}";
|
||||
logger.LogInfo($"Identical trap file for {TrapFile} already exists, renaming to {newTrapName}");
|
||||
if (TryMove(tmpFile, $"{newTrapName}"))
|
||||
return;
|
||||
}
|
||||
logger.LogInfo($"Identical trap file for {TrapFile} already exists");
|
||||
@@ -217,16 +220,16 @@ namespace Semmle.Extraction
|
||||
{
|
||||
switch (compression)
|
||||
{
|
||||
case CompressionMode.None: return "";
|
||||
case CompressionMode.Gzip: return ".gz";
|
||||
case CompressionMode.Brotli: return ".br";
|
||||
case CompressionMode.None: return ".trap";
|
||||
case CompressionMode.Gzip: return ".trap.gz";
|
||||
case CompressionMode.Brotli: return ".trap.br";
|
||||
default: throw new ArgumentOutOfRangeException(nameof(compression), compression, "Unsupported compression type");
|
||||
}
|
||||
}
|
||||
|
||||
public static string TrapPath(ILogger logger, string? folder, PathTransformer.ITransformedPath path, TrapWriter.CompressionMode trapCompression)
|
||||
{
|
||||
var filename = $"{path.Value}.trap{TrapExtension(trapCompression)}";
|
||||
var filename = $"{path.Value}{TrapExtension(trapCompression)}";
|
||||
if (string.IsNullOrEmpty(folder))
|
||||
folder = Directory.GetCurrentDirectory();
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
| Program.cs:3:24:3:27 | Main | 2 |
|
||||
| Program.cs:10:17:10:33 | GreetConditional1 | 2 |
|
||||
| Program.cs:19:17:19:21 | Greet | 2 |
|
||||
| Program.cs:25:17:25:33 | GreetConditional2 | 2 |
|
||||
@@ -0,0 +1,5 @@
|
||||
import csharp
|
||||
|
||||
from Method m
|
||||
where m.fromSource()
|
||||
select m, count(m.getBody())
|
||||
@@ -0,0 +1,40 @@
|
||||
public class Test
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
Greet();
|
||||
GreetConditional1();
|
||||
GreetConditional2();
|
||||
}
|
||||
|
||||
static void GreetConditional1()
|
||||
{
|
||||
#if A
|
||||
Console.WriteLine("Hello, A!");
|
||||
#elif C
|
||||
Console.WriteLine("Hello, C!");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void Greet()
|
||||
{
|
||||
Console.WriteLine("Hello, World!");
|
||||
}
|
||||
|
||||
#if A
|
||||
static void GreetConditional2()
|
||||
{
|
||||
Console.WriteLine("Hello, A!");
|
||||
}
|
||||
#elif B
|
||||
static void GreetConditional2()
|
||||
{
|
||||
Console.WriteLine("Hello, B!");
|
||||
}
|
||||
#else
|
||||
static void GreetConditional2()
|
||||
{
|
||||
Console.WriteLine("Hello, Others!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "8.0.101"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="**/*.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
from create_database_utils import *
|
||||
import os
|
||||
|
||||
os.environ["CODEQL_EXTRACTOR_CSHARP_OPTION_TRAP_COMPRESSION"] = "none"
|
||||
|
||||
run_codeql_database_create(['dotnet build /p:DefineConstants=A', 'dotnet build /p:DefineConstants=B'], lang="csharp")
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The extractor has been changed to not skip source files that have already been seen. This has an impact on source files that are compiled multiple times in the build process. Source files with conditional compilation preprocessor directives (such as `#if`) are now extracted for each set of preprocessor symbols that are used during the build process.
|
||||
@@ -421,7 +421,7 @@ preprocessor_directive_location(
|
||||
int loc: @location ref);
|
||||
|
||||
preprocessor_directive_compilation(
|
||||
unique int id: @preprocessor_directive ref,
|
||||
int id: @preprocessor_directive ref,
|
||||
int compilation: @compilation ref);
|
||||
|
||||
preprocessor_directive_active(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Remove unique constraint on preprocessor directive and compilation pairs
|
||||
compatibility: backwards
|
||||
@@ -83,13 +83,13 @@ java.io,66,1,256,,,,,,,,,22,,,,,,,,,,,,,,,44,,,,,,,,,,,,,,,,,,,,,,1,,249,7
|
||||
java.lang,38,3,756,,13,,,,,,1,,,,,,,,,,,,8,,,,11,,,4,,,1,,,,,,,,,,,,,,,3,,,681,75
|
||||
java.math,,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9
|
||||
java.net,23,3,278,,,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,21,,,,,,,,,,,,,,3,274,4
|
||||
java.nio,44,,361,,,,,,,,,5,,,,,,,,,,,,,,,38,,,,,,,,,1,,,,,,,,,,,,,,,259,102
|
||||
java.nio,47,,361,,,,,,,,,5,,,,,,,,,,,,,,,41,,,,,,,,,1,,,,,,,,,,,,,,,259,102
|
||||
java.rmi,,,71,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,71,
|
||||
java.security,21,,543,,,11,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,539,4
|
||||
java.sql,15,1,303,,,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,9,,,,,,,,,1,,,,303,
|
||||
java.text,,,134,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,134,
|
||||
java.time,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,88
|
||||
java.util,47,2,1218,,,,,,,,,1,,,,,,,,,,,34,,,,2,,,,5,2,,1,2,,,,,,,,,,,,,2,,,704,514
|
||||
java.util,48,2,1218,,,,,,,,,1,,,,,,,,,,,34,,,,3,,,,5,2,,1,2,,,,,,,,,,,,,2,,,704,514
|
||||
javafx.scene.web,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,
|
||||
javax.accessibility,,,31,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,31,
|
||||
javax.activation,2,,7,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,1,,,,,,,,,,,,,,,7,
|
||||
@@ -138,6 +138,7 @@ jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10
|
||||
kotlin,16,,1849,,,,,,,,,,,,,,,,,,,,,,,,14,,,,,,,,,2,,,,,,,,,,,,,,,1836,13
|
||||
liquibase.database.jvm,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,
|
||||
liquibase.statement.core,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,
|
||||
net.lingala.zip4j,2,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
net.schmizz.sshj,4,,,,,,2,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
net.sf.json,2,,338,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,321,17
|
||||
net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,5,,,,,,,,
|
||||
@@ -231,7 +232,7 @@ org.springframework.beans,,,30,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3
|
||||
org.springframework.boot.jdbc,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,
|
||||
org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13
|
||||
org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
org.springframework.core.io,3,,5,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,1,,,,,,,,,,,,,,,5,
|
||||
org.springframework.core.io,17,,5,,,,,,,,,,,,,,,,,,,,,,,,16,,,,,,,,,1,,,,,,,,,,,,,,,5,
|
||||
org.springframework.data.repository,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1
|
||||
org.springframework.http,14,,77,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,14,,,,,,,,,,,,,,,67,10
|
||||
org.springframework.jdbc.core,19,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,,,,,,,,,,,,,,
|
||||
@@ -242,7 +243,7 @@ org.springframework.ldap,47,,,,,,,,,,,,,,,,,,,33,,14,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.security.core.userdetails,2,,,,,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,
|
||||
org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32
|
||||
org.springframework.util,3,,142,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,,90,52
|
||||
org.springframework.util,10,,142,,,,,,,,,,,,,,,,,,,,,,,,10,,,,,,,,,,,,,,,,,,,,,,,,90,52
|
||||
org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13,
|
||||
org.springframework.web.client,13,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13,,,,,,,,,,,,,,3,,
|
||||
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,,
|
||||
@@ -268,6 +269,7 @@ ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,4,
|
||||
ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10,
|
||||
ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35
|
||||
retrofit2,1,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,1,
|
||||
software.amazon.awssdk.transfer.s3.model,8,,,,,,,,,,,,,,,,,,,,,,,,,,8,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.awt,,,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,5,
|
||||
sun.jvmstat.perfdata.monitor.protocol.local,3,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.jvmstat.perfdata.monitor.protocol.rmi,1,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
|
||||
|
@@ -18,10 +18,10 @@ Java framework & library support
|
||||
`Google Guava <https://guava.dev/>`_,``com.google.common.*``,,730,43,9,,,,,
|
||||
JBoss Logging,``org.jboss.logging``,,,324,,,,,,
|
||||
`JSON-java <https://github.com/stleary/JSON-java>`_,``org.json``,,236,,,,,,,
|
||||
Java Standard Library,``java.*``,10,4264,255,95,,9,,,26
|
||||
Java Standard Library,``java.*``,10,4264,259,99,,9,,,26
|
||||
Java extensions,"``javax.*``, ``jakarta.*``",69,3257,90,10,4,2,1,1,4
|
||||
Kotlin Standard Library,``kotlin*``,,1849,16,14,,,,,2
|
||||
`Spring <https://spring.io/>`_,``org.springframework.*``,38,486,122,5,,28,14,,35
|
||||
Others,"``actions.osgi``, ``antlr``, ``ch.ethz.ssh2``, ``cn.hutool.core.codec``, ``com.alibaba.druid.sql``, ``com.alibaba.fastjson2``, ``com.amazonaws.auth``, ``com.auth0.jwt.algorithms``, ``com.azure.identity``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.google.gson``, ``com.hubspot.jinjava``, ``com.jcraft.jsch``, ``com.microsoft.sqlserver.jdbc``, ``com.mitchellbosecke.pebble``, ``com.mongodb``, ``com.opensymphony.xwork2``, ``com.rabbitmq.client``, ``com.sshtools.j2ssh.authentication``, ``com.sun.crypto.provider``, ``com.sun.jndi.ldap``, ``com.sun.net.httpserver``, ``com.sun.net.ssl``, ``com.sun.rowset``, ``com.sun.security.auth.module``, ``com.sun.security.ntlm``, ``com.sun.security.sasl.digest``, ``com.thoughtworks.xstream``, ``com.trilead.ssh2``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``freemarker.cache``, ``freemarker.template``, ``groovy.lang``, ``groovy.text``, ``groovy.util``, ``hudson``, ``io.jsonwebtoken``, ``io.netty.bootstrap``, ``io.netty.buffer``, ``io.netty.channel``, ``io.netty.handler.codec``, ``io.netty.handler.ssl``, ``io.netty.handler.stream``, ``io.netty.resolver``, ``io.netty.util``, ``io.undertow.server.handlers.resource``, ``javafx.scene.web``, ``jenkins``, ``jodd.json``, ``liquibase.database.jvm``, ``liquibase.statement.core``, ``net.schmizz.sshj``, ``net.sf.json``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.acegisecurity``, ``org.antlr.runtime``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.exec``, ``org.apache.commons.httpclient.util``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.lang``, ``org.apache.commons.logging``, ``org.apache.commons.net``, ``org.apache.commons.ognl``, ``org.apache.cxf.catalog``, ``org.apache.cxf.common.classloader``, ``org.apache.cxf.common.jaxb``, ``org.apache.cxf.common.logging``, ``org.apache.cxf.configuration.jsse``, ``org.apache.cxf.helpers``, ``org.apache.cxf.resource``, ``org.apache.cxf.staxutils``, ``org.apache.cxf.tools.corba.utils``, ``org.apache.cxf.tools.util``, ``org.apache.cxf.transform``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.fs``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hadoop.hive.ql.exec``, ``org.apache.hadoop.hive.ql.metadata``, ``org.apache.hc.client5.http.async.methods``, ``org.apache.hc.client5.http.classic.methods``, ``org.apache.hc.client5.http.fluent``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.ibatis.mapping``, ``org.apache.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.shiro.mgt``, ``org.apache.sshd.client.session``, ``org.apache.struts.beanvalidation.validation.interceptor``, ``org.apache.struts2``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.apache.velocity.app``, ``org.apache.velocity.runtime``, ``org.codehaus.cargo.container.installer``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.eclipse.jetty.client``, ``org.fusesource.leveldbjni``, ``org.geogebra.web.full.main``, ``org.gradle.api.file``, ``org.hibernate``, ``org.influxdb``, ``org.jboss.vfs``, ``org.jdbi.v3.core``, ``org.jenkins.ui.icon``, ``org.jenkins.ui.symbol``, ``org.jooq``, ``org.keycloak.models.map.storage``, ``org.kohsuke.stapler``, ``org.lastaflute.web``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.owasp.esapi``, ``org.pac4j.jwt.config.encryption``, ``org.pac4j.jwt.config.signature``, ``org.scijava.log``, ``org.slf4j``, ``org.thymeleaf``, ``org.w3c.dom``, ``org.xml.sax``, ``org.xmlpull.v1``, ``org.yaml.snakeyaml``, ``play.libs.ws``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``, ``sun.awt``, ``sun.jvmstat.perfdata.monitor.protocol.local``, ``sun.jvmstat.perfdata.monitor.protocol.rmi``, ``sun.management.spi``, ``sun.misc``, ``sun.net.ftp``, ``sun.net.www.protocol.http``, ``sun.nio.ch``, ``sun.security.acl``, ``sun.security.jgss.krb5``, ``sun.security.krb5``, ``sun.security.pkcs``, ``sun.security.pkcs11``, ``sun.security.provider``, ``sun.security.ssl``, ``sun.security.x509``, ``sun.tools.jconsole``, ``sun.util.logging.internal``",132,10603,898,130,6,22,18,,208
|
||||
Totals,,311,25147,2600,369,16,128,33,1,409
|
||||
`Spring <https://spring.io/>`_,``org.springframework.*``,38,486,143,26,,28,14,,35
|
||||
Others,"``actions.osgi``, ``antlr``, ``ch.ethz.ssh2``, ``cn.hutool.core.codec``, ``com.alibaba.druid.sql``, ``com.alibaba.fastjson2``, ``com.amazonaws.auth``, ``com.auth0.jwt.algorithms``, ``com.azure.identity``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.google.gson``, ``com.hubspot.jinjava``, ``com.jcraft.jsch``, ``com.microsoft.sqlserver.jdbc``, ``com.mitchellbosecke.pebble``, ``com.mongodb``, ``com.opensymphony.xwork2``, ``com.rabbitmq.client``, ``com.sshtools.j2ssh.authentication``, ``com.sun.crypto.provider``, ``com.sun.jndi.ldap``, ``com.sun.net.httpserver``, ``com.sun.net.ssl``, ``com.sun.rowset``, ``com.sun.security.auth.module``, ``com.sun.security.ntlm``, ``com.sun.security.sasl.digest``, ``com.thoughtworks.xstream``, ``com.trilead.ssh2``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``freemarker.cache``, ``freemarker.template``, ``groovy.lang``, ``groovy.text``, ``groovy.util``, ``hudson``, ``io.jsonwebtoken``, ``io.netty.bootstrap``, ``io.netty.buffer``, ``io.netty.channel``, ``io.netty.handler.codec``, ``io.netty.handler.ssl``, ``io.netty.handler.stream``, ``io.netty.resolver``, ``io.netty.util``, ``io.undertow.server.handlers.resource``, ``javafx.scene.web``, ``jenkins``, ``jodd.json``, ``liquibase.database.jvm``, ``liquibase.statement.core``, ``net.lingala.zip4j``, ``net.schmizz.sshj``, ``net.sf.json``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.acegisecurity``, ``org.antlr.runtime``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.exec``, ``org.apache.commons.httpclient.util``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.lang``, ``org.apache.commons.logging``, ``org.apache.commons.net``, ``org.apache.commons.ognl``, ``org.apache.cxf.catalog``, ``org.apache.cxf.common.classloader``, ``org.apache.cxf.common.jaxb``, ``org.apache.cxf.common.logging``, ``org.apache.cxf.configuration.jsse``, ``org.apache.cxf.helpers``, ``org.apache.cxf.resource``, ``org.apache.cxf.staxutils``, ``org.apache.cxf.tools.corba.utils``, ``org.apache.cxf.tools.util``, ``org.apache.cxf.transform``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.fs``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hadoop.hive.ql.exec``, ``org.apache.hadoop.hive.ql.metadata``, ``org.apache.hc.client5.http.async.methods``, ``org.apache.hc.client5.http.classic.methods``, ``org.apache.hc.client5.http.fluent``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.ibatis.mapping``, ``org.apache.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.shiro.mgt``, ``org.apache.sshd.client.session``, ``org.apache.struts.beanvalidation.validation.interceptor``, ``org.apache.struts2``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.apache.velocity.app``, ``org.apache.velocity.runtime``, ``org.codehaus.cargo.container.installer``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.eclipse.jetty.client``, ``org.fusesource.leveldbjni``, ``org.geogebra.web.full.main``, ``org.gradle.api.file``, ``org.hibernate``, ``org.influxdb``, ``org.jboss.vfs``, ``org.jdbi.v3.core``, ``org.jenkins.ui.icon``, ``org.jenkins.ui.symbol``, ``org.jooq``, ``org.keycloak.models.map.storage``, ``org.kohsuke.stapler``, ``org.lastaflute.web``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.owasp.esapi``, ``org.pac4j.jwt.config.encryption``, ``org.pac4j.jwt.config.signature``, ``org.scijava.log``, ``org.slf4j``, ``org.thymeleaf``, ``org.w3c.dom``, ``org.xml.sax``, ``org.xmlpull.v1``, ``org.yaml.snakeyaml``, ``play.libs.ws``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``, ``software.amazon.awssdk.transfer.s3.model``, ``sun.awt``, ``sun.jvmstat.perfdata.monitor.protocol.local``, ``sun.jvmstat.perfdata.monitor.protocol.rmi``, ``sun.management.spi``, ``sun.misc``, ``sun.net.ftp``, ``sun.net.www.protocol.http``, ``sun.nio.ch``, ``sun.security.acl``, ``sun.security.jgss.krb5``, ``sun.security.krb5``, ``sun.security.pkcs``, ``sun.security.pkcs11``, ``sun.security.provider``, ``sun.security.ssl``, ``sun.security.x509``, ``sun.tools.jconsole``, ``sun.util.logging.internal``",132,10603,908,140,6,22,18,,208
|
||||
Totals,,311,25147,2635,404,16,128,33,1,409
|
||||
|
||||
|
||||
@@ -36,30 +36,32 @@ int lowerBound(VarAccess va) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets an access to `e`, which is either a variable or a method. */
|
||||
pragma[nomagic]
|
||||
private Expr getAnAccess(Element e) {
|
||||
result = e.(Variable).getAnAccess()
|
||||
or
|
||||
result.(MethodCall).getMethod() = e
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate lengthAccess(FieldAccess fa, Element qualifier) {
|
||||
fa.getQualifier() = getAnAccess(qualifier) and
|
||||
fa.getField().hasName("length")
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the index expression is a `VarAccess`, where the variable has been confirmed to be less
|
||||
* than the length.
|
||||
*/
|
||||
predicate lessthanLength(ArrayAccess a) {
|
||||
exists(ComparisonExpr lessThanLength, VarAccess va |
|
||||
exists(ComparisonExpr lessThanLength, VarAccess va, Element qualifier |
|
||||
va = a.getIndexExpr() and
|
||||
conditionHolds(lessThanLength, va)
|
||||
|
|
||||
lessThanLength.getGreaterOperand().(FieldAccess).getQualifier() = arrayReference(a) and
|
||||
lessThanLength.getGreaterOperand().(FieldAccess).getField().hasName("length") and
|
||||
lengthAccess(lessThanLength.getGreaterOperand(), qualifier) and
|
||||
a.getArray() = getAnAccess(qualifier) and
|
||||
lessThanLength.getLesserOperand() = va.getVariable().getAnAccess() and
|
||||
lessThanLength.isStrict()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all other references to the array accessed in the `ArrayAccess`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private Expr arrayReference(ArrayAccess arrayAccess) {
|
||||
// Array is stored in a variable.
|
||||
result = arrayAccess.getArray().(VarAccess).getVariable().getAnAccess()
|
||||
or
|
||||
// Array is returned from a method.
|
||||
result.(MethodCall).getMethod() = arrayAccess.getArray().(MethodCall).getMethod()
|
||||
}
|
||||
|
||||
@@ -1203,6 +1203,77 @@ module Http {
|
||||
* Gets the argument, if any, specifying the cookie value.
|
||||
*/
|
||||
DataFlow::Node getValueArg() { result = super.getValueArg() }
|
||||
|
||||
/**
|
||||
* Holds if the `Secure` flag of the cookie is known to have a value of `b`.
|
||||
*/
|
||||
predicate hasSecureFlag(boolean b) { super.hasSecureFlag(b) }
|
||||
|
||||
/**
|
||||
* Holds if the `HttpOnly` flag of the cookie is known to have a value of `b`.
|
||||
*/
|
||||
predicate hasHttpOnlyFlag(boolean b) { super.hasHttpOnlyFlag(b) }
|
||||
|
||||
/**
|
||||
* Holds if the `SameSite` attribute of the cookie is known to have a value of `v`.
|
||||
*/
|
||||
predicate hasSameSiteAttribute(CookieWrite::SameSiteValue v) { super.hasSameSiteAttribute(v) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A dataflow call node to a method that sets a cookie in an http response,
|
||||
* and has common keyword arguments `secure`, `httponly`, and `samesite` to set the attributes of the cookie.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
|
||||
*/
|
||||
abstract class SetCookieCall extends CookieWrite::Range, DataFlow::CallCfgNode {
|
||||
override predicate hasSecureFlag(boolean b) {
|
||||
super.hasSecureFlag(b)
|
||||
or
|
||||
exists(DataFlow::Node arg, BooleanLiteral bool | arg = this.getArgByName("secure") |
|
||||
DataFlow::localFlow(DataFlow::exprNode(bool), arg) and
|
||||
b = bool.booleanValue()
|
||||
)
|
||||
or
|
||||
not exists(this.getArgByName("secure")) and
|
||||
not exists(this.getKwargs()) and
|
||||
b = false
|
||||
}
|
||||
|
||||
override predicate hasHttpOnlyFlag(boolean b) {
|
||||
super.hasHttpOnlyFlag(b)
|
||||
or
|
||||
exists(DataFlow::Node arg, BooleanLiteral bool | arg = this.getArgByName("httponly") |
|
||||
DataFlow::localFlow(DataFlow::exprNode(bool), arg) and
|
||||
b = bool.booleanValue()
|
||||
)
|
||||
or
|
||||
not exists(this.getArgByName("httponly")) and
|
||||
not exists(this.getKwargs()) and
|
||||
b = false
|
||||
}
|
||||
|
||||
override predicate hasSameSiteAttribute(CookieWrite::SameSiteValue v) {
|
||||
super.hasSameSiteAttribute(v)
|
||||
or
|
||||
exists(DataFlow::Node arg, StringLiteral str | arg = this.getArgByName("samesite") |
|
||||
DataFlow::localFlow(DataFlow::exprNode(str), arg) and
|
||||
(
|
||||
str.getText().toLowerCase() = "strict" and
|
||||
v instanceof CookieWrite::SameSiteStrict
|
||||
or
|
||||
str.getText().toLowerCase() = "lax" and
|
||||
v instanceof CookieWrite::SameSiteLax
|
||||
or
|
||||
str.getText().toLowerCase() = "none" and
|
||||
v instanceof CookieWrite::SameSiteNone
|
||||
)
|
||||
)
|
||||
or
|
||||
not exists(this.getArgByName("samesite")) and
|
||||
not exists(this.getKwargs()) and
|
||||
v instanceof CookieWrite::SameSiteLax // Lax is the default
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides a class for modeling new cookie writes on HTTP responses. */
|
||||
@@ -1231,6 +1302,91 @@ module Http {
|
||||
* Gets the argument, if any, specifying the cookie value.
|
||||
*/
|
||||
abstract DataFlow::Node getValueArg();
|
||||
|
||||
/**
|
||||
* Holds if the `Secure` flag of the cookie is known to have a value of `b`.
|
||||
*/
|
||||
predicate hasSecureFlag(boolean b) {
|
||||
exists(StringLiteral sl |
|
||||
// `sl` is likely a substring of the header
|
||||
TaintTracking::localTaint(DataFlow::exprNode(sl), this.getHeaderArg()) and
|
||||
sl.getText().regexpMatch("(?i).*;\\s*secure(;.*|\\s*)") and
|
||||
b = true
|
||||
or
|
||||
// `sl` is the entire header
|
||||
DataFlow::localFlow(DataFlow::exprNode(sl), this.getHeaderArg()) and
|
||||
not sl.getText().regexpMatch("(?i).*;\\s*secure(;.*|\\s*)") and
|
||||
b = false
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `HttpOnly` flag of the cookie is known to have a value of `b`.
|
||||
*/
|
||||
predicate hasHttpOnlyFlag(boolean b) {
|
||||
exists(StringLiteral sl |
|
||||
// `sl` is likely a substring of the header
|
||||
TaintTracking::localTaint(DataFlow::exprNode(sl), this.getHeaderArg()) and
|
||||
sl.getText().regexpMatch("(?i).*;\\s*httponly(;.*|\\s*)") and
|
||||
b = true
|
||||
or
|
||||
// `sl` is the entire header
|
||||
DataFlow::localFlow(DataFlow::exprNode(sl), this.getHeaderArg()) and
|
||||
not sl.getText().regexpMatch("(?i).*;\\s*httponly(;.*|\\s*)") and
|
||||
b = false
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `SameSite` flag of the cookie is known to have a value of `v`.
|
||||
*/
|
||||
predicate hasSameSiteAttribute(SameSiteValue v) {
|
||||
exists(StringLiteral sl |
|
||||
// `sl` is likely a substring of the header
|
||||
TaintTracking::localTaint(DataFlow::exprNode(sl), this.getHeaderArg()) and
|
||||
(
|
||||
sl.getText().regexpMatch("(?i).*;\\s*samesite=strict(;.*|\\s*)") and
|
||||
v instanceof SameSiteStrict
|
||||
or
|
||||
sl.getText().regexpMatch("(?i).*;\\s*samesite=lax(;.*|\\s*)") and
|
||||
v instanceof SameSiteLax
|
||||
or
|
||||
sl.getText().regexpMatch("(?i).*;\\s*samesite=none(;.*|\\s*)") and
|
||||
v instanceof SameSiteNone
|
||||
)
|
||||
or
|
||||
// `sl` is the entire header
|
||||
DataFlow::localFlow(DataFlow::exprNode(sl), this.getHeaderArg()) and
|
||||
not sl.getText().regexpMatch("(?i).*;\\s*samesite=(strict|lax|none)(;.*|\\s*)") and
|
||||
v instanceof SameSiteLax // Lax is the default
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TSameSiteValue =
|
||||
TSameSiteStrict() or
|
||||
TSameSiteLax() or
|
||||
TSameSiteNone()
|
||||
|
||||
/** A possible value for the SameSite attribute of a cookie. */
|
||||
class SameSiteValue extends TSameSiteValue {
|
||||
/** Gets a string representation of this value. */
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
/** A `Strict` value of the `SameSite` attribute. */
|
||||
class SameSiteStrict extends SameSiteValue, TSameSiteStrict {
|
||||
override string toString() { result = "Strict" }
|
||||
}
|
||||
|
||||
/** A `Lax` value of the `SameSite` attribute. */
|
||||
class SameSiteLax extends SameSiteValue, TSameSiteLax {
|
||||
override string toString() { result = "Lax" }
|
||||
}
|
||||
|
||||
/** A `None` value of the `SameSite` attribute. */
|
||||
class SameSiteNone extends SameSiteValue, TSameSiteNone {
|
||||
override string toString() { result = "None" }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -219,6 +219,12 @@ class CallCfgNode extends CfgNode, LocalSourceNode {
|
||||
|
||||
/** Gets the data-flow node corresponding to the named argument of the call corresponding to this data-flow node */
|
||||
Node getArgByName(string name) { result.asCfgNode() = node.getArgByName(name) }
|
||||
|
||||
/** Gets the data-flow node corresponding to the first tuple (*) argument of the call corresponding to this data-flow node, if any. */
|
||||
Node getStarArg() { result.asCfgNode() = node.getStarArg() }
|
||||
|
||||
/** Gets the data-flow node corresponding to a dictionary (**) argument of the call corresponding to this data-flow node, if any. */
|
||||
Node getKwargs() { result.asCfgNode() = node.getKwargs() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -653,8 +653,7 @@ module AiohttpWebModel {
|
||||
/**
|
||||
* A call to `set_cookie` on a HTTP Response.
|
||||
*/
|
||||
class AiohttpResponseSetCookieCall extends Http::Server::CookieWrite::Range, DataFlow::CallCfgNode
|
||||
{
|
||||
class AiohttpResponseSetCookieCall extends Http::Server::SetCookieCall {
|
||||
AiohttpResponseSetCookieCall() {
|
||||
this = aiohttpResponseInstance().getMember("set_cookie").getACall()
|
||||
}
|
||||
|
||||
@@ -2170,7 +2170,7 @@ module PrivateDjango {
|
||||
/**
|
||||
* A call to `set_cookie` on a HTTP Response.
|
||||
*/
|
||||
class DjangoResponseSetCookieCall extends Http::Server::CookieWrite::Range,
|
||||
class DjangoResponseSetCookieCall extends Http::Server::SetCookieCall,
|
||||
DataFlow::MethodCallNode
|
||||
{
|
||||
DjangoResponseSetCookieCall() {
|
||||
|
||||
@@ -348,7 +348,7 @@ module FastApi {
|
||||
/**
|
||||
* A call to `set_cookie` on a FastAPI Response.
|
||||
*/
|
||||
private class SetCookieCall extends Http::Server::CookieWrite::Range, DataFlow::MethodCallNode {
|
||||
private class SetCookieCall extends Http::Server::SetCookieCall, DataFlow::MethodCallNode {
|
||||
SetCookieCall() { this.calls(instance(), "set_cookie") }
|
||||
|
||||
override DataFlow::Node getHeaderArg() { none() }
|
||||
|
||||
@@ -583,9 +583,7 @@ module Flask {
|
||||
*
|
||||
* See https://flask.palletsprojects.com/en/2.0.x/api/#flask.Response.set_cookie
|
||||
*/
|
||||
class FlaskResponseSetCookieCall extends Http::Server::CookieWrite::Range,
|
||||
DataFlow::MethodCallNode
|
||||
{
|
||||
class FlaskResponseSetCookieCall extends Http::Server::SetCookieCall, DataFlow::MethodCallNode {
|
||||
FlaskResponseSetCookieCall() { this.calls(Flask::Response::instance(), "set_cookie") }
|
||||
|
||||
override DataFlow::Node getHeaderArg() { none() }
|
||||
|
||||
@@ -255,7 +255,7 @@ module Pyramid {
|
||||
}
|
||||
|
||||
/** A call to `response.set_cookie`. */
|
||||
private class SetCookieCall extends Http::Server::CookieWrite::Range, DataFlow::MethodCallNode {
|
||||
private class SetCookieCall extends Http::Server::SetCookieCall, DataFlow::MethodCallNode {
|
||||
SetCookieCall() { this.calls(instance(), "set_cookie") }
|
||||
|
||||
override DataFlow::Node getHeaderArg() { none() }
|
||||
|
||||
@@ -592,7 +592,7 @@ module Tornado {
|
||||
*
|
||||
* See https://www.tornadoweb.org/en/stable/web.html#tornado.web.RequestHandler.set_cookie
|
||||
*/
|
||||
class TornadoRequestHandlerSetCookieCall extends Http::Server::CookieWrite::Range,
|
||||
class TornadoRequestHandlerSetCookieCall extends Http::Server::SetCookieCall,
|
||||
DataFlow::MethodCallNode
|
||||
{
|
||||
TornadoRequestHandlerSetCookieCall() {
|
||||
|
||||
@@ -235,9 +235,7 @@ private module Twisted {
|
||||
*
|
||||
* See https://twistedmatrix.com/documents/21.2.0/api/twisted.web.http.Request.html#addCookie
|
||||
*/
|
||||
class TwistedRequestAddCookieCall extends Http::Server::CookieWrite::Range,
|
||||
DataFlow::MethodCallNode
|
||||
{
|
||||
class TwistedRequestAddCookieCall extends Http::Server::SetCookieCall, DataFlow::MethodCallNode {
|
||||
TwistedRequestAddCookieCall() { this.calls(Twisted::Request::instance(), "addCookie") }
|
||||
|
||||
override DataFlow::Node getHeaderArg() { none() }
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>Setting the 'secure' flag on a cookie to <code>False</code> can cause it to be sent in cleartext.
|
||||
Setting the 'httponly' flag on a cookie to <code>False</code> may allow attackers access it via JavaScript.
|
||||
Setting the 'samesite' flag on a cookie to <code>'None'</code> will make the cookie to be sent in third-party
|
||||
contexts which may be attacker-controlled.</p>
|
||||
<p>Cookies without the <code>Secure</code> flag set may be transmittd using HTTP instead of HTTPS, which leaves it vulnerable to being read by a third party.</p>
|
||||
<p>Cookies without the <code>HttpOnly</code> flag set are accessible to JavaScript running in the same origin. In case of a Cross-Site Scripting (XSS) vulnerability, the cookie can be stolen by a malicious script.</p>
|
||||
<p>Cookies with the <code>SameSite</code> attribute set to <code>'None'</code> will be sent with cross-origin requests, which can be controlled by third-party JavaScript code and allow for Cross-Site Request Forgery (CSRF) attacks.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
@@ -18,9 +17,8 @@ contexts which may be attacker-controlled.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>This example shows two ways of adding a cookie to a Flask response. The first way uses <code>set_cookie</code>'s
|
||||
secure flag and the second adds the secure flag in the cookie's raw value.</p>
|
||||
<sample src="InsecureCookie.py" />
|
||||
<p>In the following examples, the cases marked GOOD show secure cookie attributes being set; whereas in the cases marked BAD they are not set.</p>
|
||||
<sample src="examples/InsecureCookie.py" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
51
python/ql/src/Security/CWE-614/InsecureCookie.ql
Normal file
51
python/ql/src/Security/CWE-614/InsecureCookie.ql
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @name Failure to use secure cookies
|
||||
* @description Insecure cookies may be sent in cleartext, which makes them vulnerable to
|
||||
* interception.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.0
|
||||
* @precision high
|
||||
* @id py/insecure-cookie
|
||||
* @tags security
|
||||
* external/cwe/cwe-614
|
||||
* external/cwe/cwe-1004
|
||||
* external/cwe/cwe-1275
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import semmle.python.Concepts
|
||||
|
||||
predicate hasProblem(Http::Server::CookieWrite cookie, string alert, int idx) {
|
||||
cookie.hasSecureFlag(false) and
|
||||
alert = "Secure" and
|
||||
idx = 0
|
||||
or
|
||||
cookie.hasHttpOnlyFlag(false) and
|
||||
alert = "HttpOnly" and
|
||||
idx = 1
|
||||
or
|
||||
cookie.hasSameSiteAttribute(any(Http::Server::CookieWrite::SameSiteNone v)) and
|
||||
alert = "SameSite" and
|
||||
idx = 2
|
||||
}
|
||||
|
||||
predicate hasAlert(Http::Server::CookieWrite cookie, string alert) {
|
||||
exists(int numProblems | numProblems = strictcount(string p | hasProblem(cookie, p, _)) |
|
||||
numProblems = 1 and
|
||||
alert = any(string prob | hasProblem(cookie, prob, _)) + " attribute"
|
||||
or
|
||||
numProblems = 2 and
|
||||
alert =
|
||||
strictconcat(string prob, int idx | hasProblem(cookie, prob, idx) | prob, " and " order by idx)
|
||||
+ " attributes"
|
||||
or
|
||||
numProblems = 3 and
|
||||
alert = "Secure, HttpOnly, and SameSite attributes"
|
||||
)
|
||||
}
|
||||
|
||||
from Http::Server::CookieWrite cookie, string alert
|
||||
where hasAlert(cookie, alert)
|
||||
select cookie, "Cookie is added without the " + alert + " properly set."
|
||||
20
python/ql/src/Security/CWE-614/examples/InsecureCookie.py
Normal file
20
python/ql/src/Security/CWE-614/examples/InsecureCookie.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from flask import Flask, request, make_response, Response
|
||||
|
||||
|
||||
@app.route("/good1")
|
||||
def good1():
|
||||
resp = make_response()
|
||||
resp.set_cookie("name", value="value", secure=True, httponly=True, samesite='Strict') # GOOD: Attributes are securely set
|
||||
return resp
|
||||
|
||||
|
||||
@app.route("/good2")
|
||||
def good2():
|
||||
resp = make_response()
|
||||
resp.headers['Set-Cookie'] = "name=value; Secure; HttpOnly; SameSite=Strict" # GOOD: Attributes are securely set
|
||||
return resp
|
||||
|
||||
@app.route("/bad1")
|
||||
resp = make_response()
|
||||
resp.set_cookie("name", value="value", samesite='None') # BAD: the SameSite attribute is set to 'None' and the 'Secure' and 'HttpOnly' attributes are set to False by default.
|
||||
return resp
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* The `py/cookie-injection` query, originally contributed to the experimental query pack by @jorgectf, has been promoted to the main query pack. This query finds instances of cookies being set without the `Secure`, `HttpOnly`, or `SameSite` attributes set to secure values.
|
||||
@@ -1,15 +0,0 @@
|
||||
from flask import Flask, request, make_response, Response
|
||||
|
||||
|
||||
@app.route("/1")
|
||||
def true():
|
||||
resp = make_response()
|
||||
resp.set_cookie("name", value="value", secure=True)
|
||||
return resp
|
||||
|
||||
|
||||
@app.route("/2")
|
||||
def flask_make_response():
|
||||
resp = make_response("hello")
|
||||
resp.headers['Set-Cookie'] = "name=value; Secure;"
|
||||
return resp
|
||||
@@ -1,31 +0,0 @@
|
||||
/**
|
||||
* @name Failure to use secure cookies
|
||||
* @description Insecure cookies may be sent in cleartext, which makes them vulnerable to
|
||||
* interception.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.0
|
||||
* @precision ???
|
||||
* @id py/insecure-cookie
|
||||
* @tags security
|
||||
* experimental
|
||||
* external/cwe/cwe-614
|
||||
*/
|
||||
|
||||
// TODO: determine precision above
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import experimental.semmle.python.Concepts
|
||||
import experimental.semmle.python.CookieHeader
|
||||
|
||||
from Cookie cookie, string alert
|
||||
where
|
||||
not cookie.isSecure() and
|
||||
alert = "secure"
|
||||
or
|
||||
not cookie.isHttpOnly() and
|
||||
alert = "httponly"
|
||||
or
|
||||
not cookie.isSameSite() and
|
||||
alert = "samesite"
|
||||
select cookie, "Cookie is added without the '" + alert + "' flag properly set."
|
||||
@@ -278,55 +278,6 @@ class CsvWriter extends DataFlow::Node instanceof CsvWriter::Range {
|
||||
DataFlow::Node getAnInput() { result = super.getAnInput() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A data-flow node that sets a cookie in an HTTP response.
|
||||
*
|
||||
* Extend this class to refine existing API models. If you want to model new APIs,
|
||||
* extend `Cookie::Range` instead.
|
||||
*/
|
||||
class Cookie extends Http::Server::CookieWrite instanceof Cookie::Range {
|
||||
/**
|
||||
* Holds if this cookie is secure.
|
||||
*/
|
||||
predicate isSecure() { super.isSecure() }
|
||||
|
||||
/**
|
||||
* Holds if this cookie is HttpOnly.
|
||||
*/
|
||||
predicate isHttpOnly() { super.isHttpOnly() }
|
||||
|
||||
/**
|
||||
* Holds if the cookie is SameSite
|
||||
*/
|
||||
predicate isSameSite() { super.isSameSite() }
|
||||
}
|
||||
|
||||
/** Provides a class for modeling new cookie writes on HTTP responses. */
|
||||
module Cookie {
|
||||
/**
|
||||
* A data-flow node that sets a cookie in an HTTP response.
|
||||
*
|
||||
* Extend this class to model new APIs. If you want to refine existing API models,
|
||||
* extend `Cookie` instead.
|
||||
*/
|
||||
abstract class Range extends Http::Server::CookieWrite::Range {
|
||||
/**
|
||||
* Holds if this cookie is secure.
|
||||
*/
|
||||
abstract predicate isSecure();
|
||||
|
||||
/**
|
||||
* Holds if this cookie is HttpOnly.
|
||||
*/
|
||||
abstract predicate isHttpOnly();
|
||||
|
||||
/**
|
||||
* Holds if the cookie is SameSite.
|
||||
*/
|
||||
abstract predicate isSameSite();
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides classes for modeling JWT encoding-related APIs. */
|
||||
module JwtEncoding {
|
||||
/**
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/**
|
||||
* Temporary: provides a class to extend current cookies to header declarations
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import semmle.python.dataflow.new.TaintTracking
|
||||
import experimental.semmle.python.Concepts
|
||||
import semmle.python.Concepts
|
||||
|
||||
/**
|
||||
* Gets a header setting a cookie.
|
||||
*
|
||||
* Given the following example:
|
||||
*
|
||||
* ```py
|
||||
* @app.route("/")
|
||||
* def flask_make_response():
|
||||
* resp = make_response("")
|
||||
* resp.headers['Set-Cookie'] = "name=value; Secure;"
|
||||
* return resp
|
||||
* ```
|
||||
*
|
||||
* * `this` would be `resp.headers['Set-Cookie'] = "name=value; Secure;"`.
|
||||
* * `isSecure()` predicate would succeed.
|
||||
* * `isHttpOnly()` predicate would fail.
|
||||
* * `isSameSite()` predicate would fail.
|
||||
* * `getName()` and `getValue()` results would be `"name=value; Secure;"`.
|
||||
*/
|
||||
class CookieHeader extends Cookie::Range instanceof Http::Server::ResponseHeaderWrite {
|
||||
CookieHeader() {
|
||||
exists(StringLiteral str |
|
||||
str.getText() = "Set-Cookie" and
|
||||
DataFlow::exprNode(str)
|
||||
.(DataFlow::LocalSourceNode)
|
||||
.flowsTo(this.(Http::Server::ResponseHeaderWrite).getNameArg())
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSecure() {
|
||||
exists(StringLiteral str |
|
||||
str.getText().regexpMatch(".*; *Secure;.*") and
|
||||
DataFlow::exprNode(str)
|
||||
.(DataFlow::LocalSourceNode)
|
||||
.flowsTo(this.(Http::Server::ResponseHeaderWrite).getValueArg())
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isHttpOnly() {
|
||||
exists(StringLiteral str |
|
||||
str.getText().regexpMatch(".*; *HttpOnly;.*") and
|
||||
DataFlow::exprNode(str)
|
||||
.(DataFlow::LocalSourceNode)
|
||||
.flowsTo(this.(Http::Server::ResponseHeaderWrite).getValueArg())
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSameSite() {
|
||||
exists(StringLiteral str |
|
||||
str.getText().regexpMatch(".*; *SameSite=(Strict|Lax);.*") and
|
||||
DataFlow::exprNode(str)
|
||||
.(DataFlow::LocalSourceNode)
|
||||
.flowsTo(this.(Http::Server::ResponseHeaderWrite).getValueArg())
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getNameArg() {
|
||||
result = this.(Http::Server::ResponseHeaderWrite).getValueArg()
|
||||
}
|
||||
|
||||
override DataFlow::Node getValueArg() {
|
||||
result = this.(Http::Server::ResponseHeaderWrite).getValueArg()
|
||||
}
|
||||
|
||||
override DataFlow::Node getHeaderArg() { none() }
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
private import experimental.semmle.python.frameworks.AsyncSsh
|
||||
private import experimental.semmle.python.frameworks.Stdlib
|
||||
private import experimental.semmle.python.frameworks.Flask
|
||||
private import experimental.semmle.python.frameworks.Django
|
||||
private import experimental.semmle.python.frameworks.LDAP
|
||||
private import experimental.semmle.python.frameworks.Netmiko
|
||||
|
||||
@@ -87,63 +87,6 @@ private module ExperimentalPrivateDjango {
|
||||
or
|
||||
result = baseClassRef().getReturn().getAMember()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a call to `set_cookie()`.
|
||||
*
|
||||
* Given the following example:
|
||||
*
|
||||
* ```py
|
||||
* def django_response(request):
|
||||
* resp = django.http.HttpResponse()
|
||||
* resp.set_cookie("name", "value", secure=True, httponly=True, samesite='Lax')
|
||||
* return resp
|
||||
* ```
|
||||
*
|
||||
* * `this` would be `resp.set_cookie("name", "value", secure=False, httponly=False, samesite='None')`.
|
||||
* * `getName()`'s result would be `"name"`.
|
||||
* * `getValue()`'s result would be `"value"`.
|
||||
* * `isSecure()` predicate would succeed.
|
||||
* * `isHttpOnly()` predicate would succeed.
|
||||
* * `isSameSite()` predicate would succeed.
|
||||
*/
|
||||
class DjangoResponseSetCookieCall extends DataFlow::MethodCallNode, Cookie::Range {
|
||||
DjangoResponseSetCookieCall() {
|
||||
this.calls(PrivateDjango::DjangoImpl::DjangoHttp::Response::HttpResponse::instance(),
|
||||
"set_cookie")
|
||||
}
|
||||
|
||||
override DataFlow::Node getNameArg() {
|
||||
result in [this.getArg(0), this.getArgByName("key")]
|
||||
}
|
||||
|
||||
override DataFlow::Node getValueArg() {
|
||||
result in [this.getArg(1), this.getArgByName("value")]
|
||||
}
|
||||
|
||||
override predicate isSecure() {
|
||||
DataFlow::exprNode(any(True t))
|
||||
.(DataFlow::LocalSourceNode)
|
||||
.flowsTo(this.(DataFlow::CallCfgNode).getArgByName("secure"))
|
||||
}
|
||||
|
||||
override predicate isHttpOnly() {
|
||||
DataFlow::exprNode(any(True t))
|
||||
.(DataFlow::LocalSourceNode)
|
||||
.flowsTo(this.(DataFlow::CallCfgNode).getArgByName("httponly"))
|
||||
}
|
||||
|
||||
override predicate isSameSite() {
|
||||
exists(StringLiteral str |
|
||||
str.getText() in ["Strict", "Lax"] and
|
||||
DataFlow::exprNode(str)
|
||||
.(DataFlow::LocalSourceNode)
|
||||
.flowsTo(this.(DataFlow::CallCfgNode).getArgByName("samesite"))
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getHeaderArg() { none() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/**
|
||||
* Provides classes modeling security-relevant aspects of the `flask` PyPI package.
|
||||
* See https://flask.palletsprojects.com/en/1.1.x/.
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import semmle.python.frameworks.Flask
|
||||
private import semmle.python.dataflow.new.DataFlow
|
||||
private import experimental.semmle.python.Concepts
|
||||
private import semmle.python.ApiGraphs
|
||||
private import semmle.python.frameworks.Flask
|
||||
|
||||
module ExperimentalFlask {
|
||||
/**
|
||||
* Gets a call to `set_cookie()`.
|
||||
*
|
||||
* Given the following example:
|
||||
*
|
||||
* ```py
|
||||
* @app.route("/")
|
||||
* def false():
|
||||
* resp = make_response()
|
||||
* resp.set_cookie("name", value="value", secure=True, httponly=True, samesite='Lax')
|
||||
* return resp
|
||||
* ```
|
||||
*
|
||||
* * `this` would be `resp.set_cookie("name", value="value", secure=False, httponly=False, samesite='None')`.
|
||||
* * `getName()`'s result would be `"name"`.
|
||||
* * `getValue()`'s result would be `"value"`.
|
||||
* * `isSecure()` predicate would succeed.
|
||||
* * `isHttpOnly()` predicate would succeed.
|
||||
* * `isSameSite()` predicate would succeed.
|
||||
*/
|
||||
class FlaskSetCookieCall extends Cookie::Range instanceof Flask::FlaskResponseSetCookieCall {
|
||||
override DataFlow::Node getNameArg() { result = this.getNameArg() }
|
||||
|
||||
override DataFlow::Node getValueArg() { result = this.getValueArg() }
|
||||
|
||||
override predicate isSecure() {
|
||||
DataFlow::exprNode(any(True t))
|
||||
.(DataFlow::LocalSourceNode)
|
||||
.flowsTo(this.(DataFlow::CallCfgNode).getArgByName("secure"))
|
||||
}
|
||||
|
||||
override predicate isHttpOnly() {
|
||||
DataFlow::exprNode(any(True t))
|
||||
.(DataFlow::LocalSourceNode)
|
||||
.flowsTo(this.(DataFlow::CallCfgNode).getArgByName("httponly"))
|
||||
}
|
||||
|
||||
override predicate isSameSite() {
|
||||
exists(StringLiteral str |
|
||||
str.getText() in ["Strict", "Lax"] and
|
||||
DataFlow::exprNode(str)
|
||||
.(DataFlow::LocalSourceNode)
|
||||
.flowsTo(this.(DataFlow::CallCfgNode).getArgByName("samesite"))
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getHeaderArg() { none() }
|
||||
}
|
||||
}
|
||||
@@ -405,7 +405,10 @@ module HttpServerHttpRedirectResponseTest implements TestSig {
|
||||
|
||||
module HttpServerCookieWriteTest implements TestSig {
|
||||
string getARelevantTag() {
|
||||
result in ["CookieWrite", "CookieRawHeader", "CookieName", "CookieValue"]
|
||||
result in [
|
||||
"CookieWrite", "CookieRawHeader", "CookieName", "CookieValue", "CookieSecure",
|
||||
"CookieHttpOnly", "CookieSameSite"
|
||||
]
|
||||
}
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
@@ -428,6 +431,20 @@ module HttpServerCookieWriteTest implements TestSig {
|
||||
element = cookieWrite.toString() and
|
||||
value = prettyNodeForInlineTest(cookieWrite.getValueArg()) and
|
||||
tag = "CookieValue"
|
||||
or
|
||||
element = cookieWrite.toString() and
|
||||
value = any(boolean b | cookieWrite.hasSecureFlag(b)).toString() and
|
||||
tag = "CookieSecure"
|
||||
or
|
||||
element = cookieWrite.toString() and
|
||||
value = any(boolean b | cookieWrite.hasHttpOnlyFlag(b)).toString() and
|
||||
tag = "CookieHttpOnly"
|
||||
or
|
||||
element = cookieWrite.toString() and
|
||||
value =
|
||||
any(Http::Server::CookieWrite::SameSiteValue v | cookieWrite.hasSameSiteAttribute(v))
|
||||
.toString() and
|
||||
tag = "CookieSameSite"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
| django_bad.py:6:5:7:52 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
|
||||
| django_bad.py:6:5:7:52 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
|
||||
| django_bad.py:6:5:7:52 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
|
||||
| django_bad.py:13:5:13:26 | ControlFlowNode for Subscript | Cookie is added without the 'httponly' flag properly set. |
|
||||
| django_bad.py:13:5:13:26 | ControlFlowNode for Subscript | Cookie is added without the 'samesite' flag properly set. |
|
||||
| django_bad.py:13:5:13:26 | ControlFlowNode for Subscript | Cookie is added without the 'secure' flag properly set. |
|
||||
| django_bad.py:19:5:21:66 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
|
||||
| django_bad.py:19:5:21:66 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
|
||||
| django_bad.py:19:5:21:66 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
|
||||
| django_bad.py:27:5:27:26 | ControlFlowNode for Subscript | Cookie is added without the 'httponly' flag properly set. |
|
||||
| django_bad.py:27:5:27:26 | ControlFlowNode for Subscript | Cookie is added without the 'samesite' flag properly set. |
|
||||
| django_bad.py:27:5:27:26 | ControlFlowNode for Subscript | Cookie is added without the 'secure' flag properly set. |
|
||||
| django_good.py:19:5:19:44 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
|
||||
| django_good.py:19:5:19:44 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
|
||||
| django_good.py:19:5:19:44 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
|
||||
| flask_bad.py:9:5:10:52 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
|
||||
| flask_bad.py:9:5:10:52 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
|
||||
| flask_bad.py:9:5:10:52 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
|
||||
| flask_bad.py:17:5:17:30 | ControlFlowNode for Subscript | Cookie is added without the 'httponly' flag properly set. |
|
||||
| flask_bad.py:17:5:17:30 | ControlFlowNode for Subscript | Cookie is added without the 'samesite' flag properly set. |
|
||||
| flask_bad.py:17:5:17:30 | ControlFlowNode for Subscript | Cookie is added without the 'secure' flag properly set. |
|
||||
| flask_bad.py:24:5:25:52 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
|
||||
| flask_bad.py:24:5:25:52 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
|
||||
| flask_bad.py:24:5:25:52 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
|
||||
| flask_bad.py:32:5:32:30 | ControlFlowNode for Subscript | Cookie is added without the 'httponly' flag properly set. |
|
||||
| flask_bad.py:32:5:32:30 | ControlFlowNode for Subscript | Cookie is added without the 'samesite' flag properly set. |
|
||||
| flask_bad.py:32:5:32:30 | ControlFlowNode for Subscript | Cookie is added without the 'secure' flag properly set. |
|
||||
| flask_good.py:23:5:23:57 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
|
||||
| flask_good.py:23:5:23:57 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
|
||||
| flask_good.py:23:5:23:57 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
|
||||
@@ -1 +0,0 @@
|
||||
experimental/Security/CWE-614/InsecureCookie.ql
|
||||
@@ -1,28 +0,0 @@
|
||||
import django.http
|
||||
|
||||
|
||||
def django_response(request):
|
||||
resp = django.http.HttpResponse()
|
||||
resp.set_cookie("name", "value", secure=False,
|
||||
httponly=False, samesite='None')
|
||||
return resp
|
||||
|
||||
|
||||
def django_response():
|
||||
response = django.http.HttpResponse()
|
||||
response['Set-Cookie'] = "name=value; SameSite=None;"
|
||||
return response
|
||||
|
||||
|
||||
def django_response(request):
|
||||
resp = django.http.HttpResponse()
|
||||
resp.set_cookie(django.http.request.GET.get("name"),
|
||||
django.http.request.GET.get("value"),
|
||||
secure=False, httponly=False, samesite='None')
|
||||
return resp
|
||||
|
||||
|
||||
def django_response():
|
||||
response = django.http.HttpResponse()
|
||||
response['Set-Cookie'] = f"{django.http.request.GET.get('name')}={django.http.request.GET.get('value')}; SameSite=None;"
|
||||
return response
|
||||
@@ -1,20 +0,0 @@
|
||||
import django.http
|
||||
|
||||
|
||||
def django_response(request):
|
||||
resp = django.http.HttpResponse()
|
||||
resp['Set-Cookie'] = "name=value; Secure; HttpOnly; SameSite=Lax;"
|
||||
return resp
|
||||
|
||||
|
||||
def django_response(request):
|
||||
resp = django.http.HttpResponse()
|
||||
resp.set_cookie("name", "value", secure=True,
|
||||
httponly=True, samesite='Lax')
|
||||
return resp
|
||||
|
||||
|
||||
def indeterminate(secure):
|
||||
resp = django.http.HttpResponse()
|
||||
resp.set_cookie("name", "value", secure)
|
||||
return resp
|
||||
@@ -1,37 +0,0 @@
|
||||
from flask import Flask, request, make_response, Response
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
@app.route("/1")
|
||||
def false():
|
||||
resp = make_response()
|
||||
resp.set_cookie("name", value="value", secure=False,
|
||||
httponly=False, samesite='None')
|
||||
return resp
|
||||
|
||||
|
||||
@app.route("/2")
|
||||
def flask_Response():
|
||||
resp = Response()
|
||||
resp.headers['Set-Cookie'] = "name=value; SameSite=None;"
|
||||
return resp
|
||||
|
||||
|
||||
@app.route("/3")
|
||||
def false():
|
||||
resp = make_response()
|
||||
resp.set_cookie(request.args["name"], value=request.args["value"], secure=False,
|
||||
httponly=False, samesite='None')
|
||||
return resp
|
||||
|
||||
|
||||
@app.route("/4")
|
||||
def flask_Response():
|
||||
resp = Response()
|
||||
resp.headers['Set-Cookie'] = f"{request.args['name']}={request.args['value']}; SameSite=None;"
|
||||
return resp
|
||||
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# app.run(debug=True)
|
||||
@@ -1,28 +0,0 @@
|
||||
from flask import Flask, request, make_response, Response
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
@app.route("/1")
|
||||
def true():
|
||||
resp = make_response()
|
||||
resp.set_cookie("name", value="value", secure=True,
|
||||
httponly=True, samesite='Lax')
|
||||
return resp
|
||||
|
||||
|
||||
@app.route("/2")
|
||||
def flask_Response():
|
||||
resp = Response()
|
||||
resp.headers['Set-Cookie'] = "name=value; Secure; HttpOnly; SameSite=Lax;"
|
||||
return resp
|
||||
|
||||
|
||||
def indeterminate(secure):
|
||||
resp = make_response()
|
||||
resp.set_cookie("name", value="value", secure=secure)
|
||||
return resp
|
||||
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# app.run(debug=True)
|
||||
@@ -96,10 +96,12 @@ async def streaming_response(request): # $ requestHandler
|
||||
async def setting_cookie(request): # $ requestHandler
|
||||
resp = web.Response(text="foo") # $ HttpResponse mimetype=text/plain responseBody="foo"
|
||||
resp.cookies["key"] = "value" # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.headers["Set-Cookie"] = "key2=value2" # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2"
|
||||
resp.set_cookie("key3", "value3") # $ CookieWrite CookieName="key3" CookieValue="value3"
|
||||
resp.set_cookie(name="key3", value="value3") # $ CookieWrite CookieName="key3" CookieValue="value3"
|
||||
resp.headers["Set-Cookie"] = "key2=value2" # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie("key3", "value3") # $ CookieWrite CookieName="key3" CookieValue="value3" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(name="key3", value="value3") # $ CookieWrite CookieName="key3" CookieValue="value3" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.del_cookie("key4") # $ CookieWrite CookieName="key4"
|
||||
resp.set_cookie(name="key5", value="value5", secure=True, httponly=True, samesite="Strict") # $ CookieWrite CookieName="key5" CookieValue="value5" CookieSecure=true CookieHttpOnly=true CookieSameSite=Strict
|
||||
resp.headers["Set-Cookie"] = "key6=value6; Secure; HttpOnly; SameSite=Strict" # $ headerWriteName="Set-Cookie" headerWriteValue="key6=value6; Secure; HttpOnly; SameSite=Strict" CookieWrite CookieRawHeader="key6=value6; Secure; HttpOnly; SameSite=Strict" CookieSecure=true CookieHttpOnly=true CookieSameSite=Strict
|
||||
return resp
|
||||
|
||||
|
||||
|
||||
@@ -128,11 +128,14 @@ def safe__custom_json_response(request):
|
||||
|
||||
def setting_cookie(request):
|
||||
resp = HttpResponse() # $ HttpResponse mimetype=text/html
|
||||
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.set_cookie(key="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.headers["Set-Cookie"] = "key2=value2" # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2"
|
||||
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(key="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.headers["Set-Cookie"] = "key2=value2" # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.cookies["key3"] = "value3" # $ CookieWrite CookieName="key3" CookieValue="value3"
|
||||
resp.delete_cookie("key4") # $ CookieWrite CookieName="key4"
|
||||
resp.delete_cookie(key="key4") # $ CookieWrite CookieName="key4"
|
||||
resp["Set-Cookie"] = "key5=value5" # $ headerWriteName="Set-Cookie" headerWriteValue="key5=value5" CookieWrite CookieRawHeader="key5=value5"
|
||||
resp["Set-Cookie"] = "key5=value5" # $ headerWriteName="Set-Cookie" headerWriteValue="key5=value5" CookieWrite CookieRawHeader="key5=value5" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(key="key6", value="value6", secure=True, httponly=False, samesite="None") # $ CookieWrite CookieName="key6" CookieValue="value6" CookieSecure=true CookieHttpOnly=false CookieSameSite=None
|
||||
kwargs = {'secure': True}
|
||||
resp.set_cookie(key="key7", value="value7", **kwargs) # $ CookieWrite CookieName="key7" CookieValue="value7"
|
||||
return resp
|
||||
|
||||
@@ -9,10 +9,11 @@ app = FastAPI()
|
||||
|
||||
@app.get("/response_parameter") # $ routeSetup="/response_parameter"
|
||||
async def response_parameter(response: Response): # $ requestHandler
|
||||
response.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
response.set_cookie(key="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
response.headers.append("Set-Cookie", "key2=value2") # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2"
|
||||
response.headers.append(key="Set-Cookie", value="key2=value2") # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2"
|
||||
response.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
response.set_cookie(key="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
response.set_cookie(key="key", value="value", secure=False, httponly=True, samesite="Lax") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=true CookieSameSite=Lax
|
||||
response.headers.append("Set-Cookie", "key2=value2") # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
response.headers.append(key="Set-Cookie", value="key2=value2") # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
response.headers["X-MyHeader"] = "header-value" # $ headerWriteName="X-MyHeader" headerWriteValue="header-value"
|
||||
response.status_code = 418
|
||||
return {"message": "response as parameter"} # $ HttpResponse mimetype=application/json responseBody=Dict
|
||||
@@ -44,7 +45,7 @@ async def response_parameter_custom_type(response: MyXmlResponse): # $ requestHa
|
||||
# propagated to the final response though.
|
||||
print(type(response))
|
||||
assert type(response) == fastapi.responses.Response
|
||||
response.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
response.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
response.headers["Custom-Response-Type"] = "yes, but only after function has run" # $ headerWriteName="Custom-Response-Type" headerWriteValue="yes, but only after function has run"
|
||||
xml_data = "<foo>FOO</foo>"
|
||||
return xml_data # $ HttpResponse responseBody=xml_data mimetype=application/xml
|
||||
|
||||
@@ -203,12 +203,17 @@ def redirect_simple(): # $requestHandler
|
||||
# Cookies
|
||||
################################################################################
|
||||
|
||||
def unk():
|
||||
return
|
||||
|
||||
@app.route("/setting_cookie") # $routeSetup="/setting_cookie"
|
||||
def setting_cookie(): # $requestHandler
|
||||
resp = make_response() # $ HttpResponse mimetype=text/html
|
||||
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.set_cookie(key="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.headers.add("Set-Cookie", "key2=value2") # $ headerWriteNameUnsanitized="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2"
|
||||
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(key="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(key="key", value="value", secure=True, httponly=True, samesite="Strict") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=true CookieHttpOnly=true CookieSameSite=Strict
|
||||
resp.set_cookie(key="key", value="value", secure=unk(), httponly=unk(), samesite=unk()) # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.headers.add("Set-Cookie", "key2=value2") # $ headerWriteNameUnsanitized="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.delete_cookie("key3") # $ CookieWrite CookieName="key3"
|
||||
resp.delete_cookie(key="key3") # $ CookieWrite CookieName="key3"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
@@ -86,8 +86,9 @@ def test2(request): # $ requestHandler
|
||||
def test3(ctx, req): # $ requestHandler
|
||||
ensure_tainted(req) # $ tainted
|
||||
resp = req.response # $ HttpResponse mimetype=text/html
|
||||
resp.set_cookie("hi", "there") # $ CookieWrite CookieName="hi" CookieValue="there"
|
||||
resp.set_cookie(value="there", name="hi") # $ CookieWrite CookieName="hi" CookieValue="there"
|
||||
resp.set_cookie("hi", "there") # $ CookieWrite CookieName="hi" CookieValue="there" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(value="there", name="hi") # $ CookieWrite CookieName="hi" CookieValue="there" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie("hi", "there", secure=True, httponly=True, samesite="Strict") # $ CookieWrite CookieName="hi" CookieValue="there" CookieSecure=true CookieHttpOnly=true CookieSameSite=Strict
|
||||
return "Ok" # $ HttpResponse responseBody="Ok" mimetype=text/html
|
||||
|
||||
@view_config(route_name="test4", renderer="string") # $ routeSetup
|
||||
|
||||
@@ -15,8 +15,8 @@ def plain_text_response(request): # $ requestHandler
|
||||
# this response is not the standard way to use the Djagno REST framework, but it
|
||||
# certainly is possible -- notice that the response contains double quotes
|
||||
data = 'this response will contain double quotes since it was a string'
|
||||
resp = Response(data, None, None, None, None, "text/plain") # $ HttpResponse mimetype=text/plain responseBody=data
|
||||
resp = Response(data=data, content_type="text/plain") # $ HttpResponse mimetype=text/plain responseBody=data
|
||||
resp = Response(data, None, None, None, None, "text/plain") # $ HttpResponse responseBody=data mimetype=text/plain
|
||||
resp = Response(data=data, content_type="text/plain") # $ HttpResponse responseBody=data mimetype=text/plain
|
||||
return resp
|
||||
|
||||
################################################################################
|
||||
@@ -26,9 +26,9 @@ def plain_text_response(request): # $ requestHandler
|
||||
@api_view
|
||||
def setting_cookie(request):
|
||||
resp = Response() # $ HttpResponse
|
||||
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.set_cookie(key="key4", value="value") # $ CookieWrite CookieName="key4" CookieValue="value"
|
||||
resp.headers["Set-Cookie"] = "key2=value2" # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2"
|
||||
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(key="key4", value="value") # $ CookieWrite CookieName="key4" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.headers["Set-Cookie"] = "key2=value2" # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.cookies["key3"] = "value3" # $ CookieWrite CookieName="key3" CookieValue="value3"
|
||||
resp.delete_cookie("key4") # $ CookieWrite CookieName="key4"
|
||||
resp.delete_cookie(key="key4") # $ CookieWrite CookieName="key4"
|
||||
|
||||
@@ -68,9 +68,9 @@ def function_based_view(request: Request): # $ requestHandler
|
||||
@api_view(["GET", "POST"])
|
||||
def cookie_test(request: Request): # $ requestHandler
|
||||
resp = Response("wat") # $ HttpResponse
|
||||
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.set_cookie(key="key4", value="value") # $ CookieWrite CookieName="key4" CookieValue="value"
|
||||
resp.headers["Set-Cookie"] = "key2=value2" # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2"
|
||||
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(key="key4", value="value") # $ CookieWrite CookieName="key4" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.headers["Set-Cookie"] = "key2=value2" # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.cookies["key3"] = "value3" # $ CookieWrite CookieName="key3" CookieValue="value3"
|
||||
return resp
|
||||
|
||||
|
||||
@@ -65,12 +65,13 @@ class ExampleConnectionWrite(tornado.web.RequestHandler):
|
||||
class CookieWriting(tornado.web.RequestHandler):
|
||||
def get(self): # $ requestHandler
|
||||
self.write("foo") # $ HttpResponse mimetype=text/html responseBody="foo"
|
||||
self.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
self.set_cookie(name="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
self.set_header("Set-Cookie", "key2=value2") # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2"
|
||||
self.add_header("Set-Cookie", "key3=value3") # $ headerWriteName="Set-Cookie" headerWriteValue="key3=value3" CookieWrite CookieRawHeader="key3=value3"
|
||||
self.request.headers.add("Set-Cookie", "key4=value4") # $ headerWriteName="Set-Cookie" headerWriteValue="key4=value4" CookieWrite CookieRawHeader="key4=value4"
|
||||
self.request.headers["Set-Cookie"] = "key5=value5" # $ headerWriteName="Set-Cookie" headerWriteValue="key5=value5" CookieWrite CookieRawHeader="key5=value5"
|
||||
self.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
self.set_cookie(name="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
self.set_cookie("key", "value", secure=True, httponly=True, samesite="strict") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=true CookieHttpOnly=true CookieSameSite=Strict
|
||||
self.set_header("Set-Cookie", "key2=value2") # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
self.add_header("Set-Cookie", "key3=value3") # $ headerWriteName="Set-Cookie" headerWriteValue="key3=value3" CookieWrite CookieRawHeader="key3=value3" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
self.request.headers.add("Set-Cookie", "key4=value4") # $ headerWriteName="Set-Cookie" headerWriteValue="key4=value4" CookieWrite CookieRawHeader="key4=value4" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
self.request.headers["Set-Cookie"] = "key5=value5" # $ headerWriteName="Set-Cookie" headerWriteValue="key5=value5" CookieWrite CookieRawHeader="key5=value5" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
|
||||
|
||||
def make_app():
|
||||
|
||||
@@ -51,13 +51,14 @@ class CookieWriting(Resource):
|
||||
"""Examples of providing values in response that is not in the body
|
||||
"""
|
||||
def render_GET(self, request: Request): # $ requestHandler
|
||||
request.addCookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
request.addCookie(k="key", v="value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
request.addCookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
request.addCookie(k="key", v="value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
request.addCookie("key", "value", secure=True, httponly=True, samesite="strict") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=true CookieHttpOnly=true CookieSameSite=Strict
|
||||
val = "key2=value"
|
||||
request.cookies.append(val) # $ CookieWrite CookieRawHeader=val
|
||||
request.cookies.append(val) # $ CookieWrite CookieRawHeader=val CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
|
||||
request.responseHeaders.addRawHeader("key", "value")
|
||||
request.setHeader("Set-Cookie", "key3=value3") # $ MISSING: CookieWrite CookieRawHeader="key3=value3"
|
||||
request.setHeader("Set-Cookie", "key3=value3") # $ MISSING: CookieWrite CookieRawHeader="key3=value3" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
|
||||
return b"" # $ HttpResponse mimetype=text/html responseBody=b""
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
| test.py:10:5:10:37 | ControlFlowNode for Attribute() | Cookie is added without the Secure and HttpOnly attributes properly set. |
|
||||
| test.py:11:5:11:50 | ControlFlowNode for Attribute() | Cookie is added without the HttpOnly attribute properly set. |
|
||||
| test.py:12:5:12:52 | ControlFlowNode for Attribute() | Cookie is added without the Secure attribute properly set. |
|
||||
| test.py:13:5:13:56 | ControlFlowNode for Attribute() | Cookie is added without the Secure and HttpOnly attributes properly set. |
|
||||
| test.py:14:5:14:53 | ControlFlowNode for Attribute() | Cookie is added without the Secure and HttpOnly attributes properly set. |
|
||||
| test.py:15:5:15:54 | ControlFlowNode for Attribute() | Cookie is added without the Secure, HttpOnly, and SameSite attributes properly set. |
|
||||
| test.py:16:5:16:69 | ControlFlowNode for Attribute() | Cookie is added without the HttpOnly attribute properly set. |
|
||||
| test.py:17:5:17:71 | ControlFlowNode for Attribute() | Cookie is added without the Secure attribute properly set. |
|
||||
| test.py:18:5:18:67 | ControlFlowNode for Attribute() | Cookie is added without the HttpOnly and SameSite attributes properly set. |
|
||||
| test.py:19:5:19:69 | ControlFlowNode for Attribute() | Cookie is added without the Secure and SameSite attributes properly set. |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE-614/InsecureCookie.ql
|
||||
@@ -0,0 +1,20 @@
|
||||
from flask import Flask, request, make_response
|
||||
import lxml.etree
|
||||
import markupsafe
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/test")
|
||||
def test():
|
||||
resp = make_response()
|
||||
resp.set_cookie("key1", "value1")
|
||||
resp.set_cookie("key2", "value2", secure=True)
|
||||
resp.set_cookie("key2", "value2", httponly=True)
|
||||
resp.set_cookie("key2", "value2", samesite="Strict")
|
||||
resp.set_cookie("key2", "value2", samesite="Lax")
|
||||
resp.set_cookie("key2", "value2", samesite="None")
|
||||
resp.set_cookie("key2", "value2", secure=True, samesite="Strict")
|
||||
resp.set_cookie("key2", "value2", httponly=True, samesite="Strict")
|
||||
resp.set_cookie("key2", "value2", secure=True, samesite="None")
|
||||
resp.set_cookie("key2", "value2", httponly=True, samesite="None")
|
||||
resp.set_cookie("key2", "value2", secure=True, httponly=True, samesite="Strict")
|
||||
Reference in New Issue
Block a user