- Jedis Codeql Setup
- Jedis Codeql Modeling
- Modeling sqlite as dependency
- Modeling jedis as dependency
- Identify usage of injection-related models in existing queries
- for java, the sqltainted query will find the sink, not the source yet.
- vulnerable sample
Jedis Codeql Setup
- fork at https://github.com/hohn/jedis
-
github db build: enable code scanning, advanced config
- only java-kotlin, build-mode: none.
- creates https://github.com/hohn/jedis/blob/master/.github/workflows/codeql.yml
- action run at https://github.com/hohn/jedis/actions/workflows/codeql.yml
-
db download
# list dbs curl -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/hohn/jedis/code-scanning/analyses # Get DB via curl cd ~/work-gh/codeql-lab/assets curl -H "Authorization: token $GITHUB_TOKEN" \ -H "Accept: application/zip" \ -L \ https://api.github.com/repos/hohn/jedis/code-scanning/codeql/databases/java \ -o jedis-database-gh.zip - db at ~/work-gh/codeql-lab/assets/jedis-database-gh.zip
-
local db build:
cd ~/work-gh/codeql-lab/ # Add the submodule git submodule add https://github.com/hohn/jedis extern/jedis # Initialize and clone the submodule git submodule update --init --recursive # Build directly once to resolve any errors cd ~/work-gh/codeql-lab/extern/jedis mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V # Build under codeql # Step 1: Clean any prior Maven builds cd ~/work-gh/codeql-lab/extern/jedis mvn clean # Step 2: Run CodeQL DB creation with mvn install cd ~/work-gh/codeql-lab codeql database create assets/jedis-db-local \ --overwrite \ --language=java \ --command="mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V" \ --source-root=extern/jedis
Jedis Codeql Modeling
Setup and Start
# Step 1: Go to your CodeQL lab directory
cd ~/work-gh/codeql-lab
# Step 2: Extract the prebuilt CodeQL database for the Jedis project
unzip -q assets/jedis-db-local.zip
# Step 3: Extract the CodeQL command-line tools (platform-specific)
unzip -q assets/codeql-osx64.zip
# Step 4: Change directory to the unpacked CodeQL CLI tools
cd ~/work-gh/codeql-lab/codeql
# Step 5: Add the CodeQL CLI directory to your shell's PATH
# This allows you to run `codeql` from any location
export PATH="$(pwd):$PATH"
# Step 6: Launch Visual Studio Code with the lab workspace
code qllab.code-workspace
# In VS Code, perform the following setup manually:
# - Set the current database to: jedis-db-local
# (Usually from the CodeQL extension pane – this connects the UI to your analysis DB)
# - Set the CodeQL CLI executable to: ~/work-gh/codeql-lab/codeql/codeql
# (Tell the extension where to find the CLI you just extracted)
# - In the CodeQL extension tab, scroll to the bottom and select:
# 'CodeQL: Method modeling' to begin a guided modeling tutorial
Using the Editor
Note that just by starting CodeQL: Method modeling, the new file
.github/codeql/extensions/jedis-db-local-java/codeql-pack.yml
is created.
Relevant Queries
A quick grep shows
grep 'java.*modelgen' files |grep -v test/
ql/java/ql/src/utils/modelgenerator
ql/java/ql/src/utils/modelgenerator/CaptureNeutralModels.ql
ql/java/ql/src/utils/modelgenerator/CaptureTypeBasedSummaryModels.ql
ql/java/ql/src/utils/modelgenerator/CaptureSinkModels.ql
ql/java/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql
ql/java/ql/src/utils/modelgenerator/internal
ql/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll
ql/java/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll
ql/java/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll
ql/java/ql/src/utils/modelgenerator/CaptureSummaryModels.ql
ql/java/ql/src/utils/modelgenerator/RegenerateModels.py
ql/java/ql/src/utils/modelgenerator/CaptureSourceModels.ql
ql/java/ql/src/utils/modelgenerator/debug
ql/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql
ql/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql
ql/java/ql/src/utils/modelgenerator/debug/README.md
Primary Query File
The primary query file is
../ql/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll
This acts as the backbone, exposing traits like:
- SummaryModelGeneratorInput
- ModelGeneratorCommonInput
- isPrimitiveTypeUsedForBulkData(…)
-
Likely common predicates such as:
- hasNoSideEffects(…)
- isNeutralReturn(…)
- isBulkGetterLike(…)
These are imported by:
- CaptureSinkModels.ql
- CaptureSummaryModels.ql
- CaptureContentSummaryModels.ql
- CaptureHeuristicSummaryModels.ql
-
Design: Three Modeling Targets
Module Implements Purpose —————————- ——————————- ———————————————— `SummaryModelGeneratorInput` `SummaryModelGeneratorInputSig` Models pass-through or computed summaries `SourceModelGeneratorInput` `SourceModelGeneratorInputSig` Models user-controlled or origin taint sources `SinkModelGeneratorInput` `SinkModelGeneratorInputSig` Models taint sinks (e.g., logging, SQL, network) -
Shared Input System ModelGeneratorCommonInput provides:
- Name formatting
- Type filtering (isRelevantType)
- Signature stringification
- “Approximate output” helpers like Argument[pos].Element
This gives a stable data interface to the rest of the system.
-
Filtering logic
private predicate relevant(Callable api) { api.isPublic() and api.getDeclaringType().isPublic() and api.fromSource() and not isUninterestingForModels(api) and not isInfrequentlyUsed(api.getCompilationUnit()) }
Experiment with test clone
The needed imports are private, so clone
ql/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql
and experiment there.
import java
import utils.modelgenerator.internal.CaptureModels
import SourceModels
import utils.test.InlineMadTest
module InlineMadTestConfig implements InlineMadTestConfigSig {
string getCapturedModel(Callable c) { result = Heuristic::captureSource(c) }
string getKind() { result = "source" }
}
import InlineMadTest<InlineMadTestConfig>
Modeling sqlite as dependency
The tree
src-sqlite
contains a trivial sample taken from a workshop. It uses
sqlite-jdbc-3.36.0.1.jar, so we can use it to illustrate modeling on a smaller
example.
Modeling jedis as dependency
Running the model editor a jedis db models jedis dependencies; we need jedis as dependency to model it.
Using the
- model as depedency option
the query run by model editor is
/Users/hohn/work-gh/codeql-lab/ql/java/ql/src/utils/modeleditor/FrameworkModeEndpoints.ql
The columns of the query
from PublicEndpointFromSource endpoint, boolean supported, string type
where
supported = isSupported(endpoint) and
type = supportedType(endpoint)
select endpoint, endpoint.getPackageName(), endpoint.getTypeName(), endpoint.getName(),
endpoint.getParameterTypes(), supported,
endpoint.getCompilationUnit().getParentContainer().getBaseName(), type
indicate the modeling state:
- supported == true
- shows as 'Method already modeled' in the editor
- supported == false
- shows as 'Unmodeled' in the editor
Files involved:
-
Note that just by starting
CodeQL: Method modeling, the new file.github/codeql/extensions/jedis-db-local-java/codeql-pack.yml
is created.
-
After selection and saving, results are in
~/work-gh/codeql-lab/.github/codeql/extensions/jedis-db-local-java/models/redis.clients.jedis.model.yml
The sink added:
extensions: ... - addsTo: pack: codeql/java-all extensible: sinkModel data: - ["redis.clients.jedis","Jedis",true,"eval","(String)","","Argument[0]","code-injection","manual"] ...
For the files to be picked up requires the entry
"codeQL.runningQueries.useExtensionPacks": "all"
in
/Users/hohn/work-gh/codeql-lab/qllab.code-workspace
{
"folders": [
{
"path": "."
}
],
"settings": {
"omnisharp.autoStart": false,
"codeQL.githubDatabase.download": "never",
"sarif-viewer.connectToGithubCodeScanning": "off",
"codeQL.cli.executablePath": "/Users/hohn/work-gh/codeql-lab/codeql/codeql",
"codeQL.runningQueries.useExtensionPacks": "all"
}
}
In some cases (older vs code?), the file
/Users/hohn/work-gh/codeql-lab/.vscode/settings.json
needs that entry.
With the additions from the model editor, the query
import java
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.DataFlow
from DataFlow::Node n, string type
where sinkNode(n, type)
and type = "code-injection"
select n, type
lists the sink arguments to eval():
example.ql on jedis-db-local - finished in 2 seconds (14 results) [7/8/2025, 12:51:20 PM]
| 1 | script | code-injection |
| 2 | getBytes(…) | code-injection |
| 3 | script | code-injection |
| 4 | script | code-injection |
| 5 | script | code-injection |
| 6 | script | code-injection |
| 7 | "return redis.call('get','foo')" | code-injection |
| 8 | "return redis.call('get','foo')" | code-injection |
| 9 | encode(…) | code-injection |
| 10 | encode(…) | code-injection |
| 11 | "return redis.call('get','foo')" | code-injection |
| 12 | "return redis.call('get','foo')" | code-injection |
| 13 | script | code-injection |
| 14 | "return {}" | code-injection |
Identify usage of injection-related models in existing queries
To verify whether existing CodeQL queries make use of the injection-related models, we can search for files in the `ql/java` and `ql/cpp` directories that contain the string `-injection`. This string often appears in taint-tracking configuration or query metadata.
Java Queries
The following command locates `.ql` and `.qll` files in the Java query suite that reference `-injection`:
rg -l -- '-injection' ql/java | grep '\.qll*'
Example output:
ql/java/ql/src/Security/CWE/CWE-643/XPathInjection.ql
ql/java/ql/src/Security/CWE/CWE-078/ExecTainted.ql
ql/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql
ql/java/ql/src/Security/CWE/CWE-117/LogInjection.ql
ql/java/ql/src/Security/CWE/CWE-470/FragmentInjection.ql
ql/java/ql/src/Security/CWE/CWE-470/FragmentInjectionInPreferenceActivity.ql
ql/java/ql/src/Security/CWE/CWE-730/RegexInjection.ql
ql/java/ql/lib/semmle/code/java/security/XsltInjection.qll
ql/java/ql/src/Security/CWE/CWE-090/LdapInjection.ql
ql/java/ql/lib/semmle/code/java/security/GroovyInjection.qll
ql/java/ql/lib/semmle/code/java/security/XPath.qll
ql/java/ql/lib/semmle/code/java/security/TaintedEnvironmentVariableQuery.qll
ql/java/ql/src/Security/CWE/CWE-074/XsltInjection.ql
ql/java/ql/src/Security/CWE/CWE-074/JndiInjection.ql
...
ql/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll
These files include both top-level queries (under `src/Security/…`) and reusable model libraries (under `lib/semmle/…`). Experimental and framework-specific queries are also included.
C++ Queries
Likewise, to check for C++ queries that reference `-injection`, use:
rg -l -- '-injection' ql/cpp | grep '\.qll*'
Example output:
ql/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql
ql/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql
ql/cpp/ql/src/experimental/Security/CWE/CWE-078/WordexpTainted.ql
ql/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql
These files indicate active use of injection-related taint tracking in the C++ suite as well.
TODO for java, the sqltainted query will find the sink, not the source yet.
TODO vulnerable sample
For .eval() to show in a query, it has to be used in an application. So we modify src-sqlite/AddUser.java for jedis.