mirror of
https://github.com/github/codeql.git
synced 2026-06-12 08:21:09 +02:00
Compare commits
1 Commits
copilot/co
...
idrissrio/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3d0cebe81 |
208
.github/workflows/go-version-update.yml
vendored
208
.github/workflows/go-version-update.yml
vendored
@@ -1,208 +0,0 @@
|
||||
name: Update Go version
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 3 * * 1" # Run weekly on Mondays at 3 AM UTC (1 = Monday)
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-go-version:
|
||||
name: Check and update Go version
|
||||
if: github.repository == 'github/codeql'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Git
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Fetch latest Go version
|
||||
id: fetch-version
|
||||
run: |
|
||||
LATEST_GO_VERSION=$(curl -s https://go.dev/dl/?mode=json | jq -r '.[0].version')
|
||||
|
||||
if [ -z "$LATEST_GO_VERSION" ] || [ "$LATEST_GO_VERSION" = "null" ]; then
|
||||
echo "Error: Failed to fetch latest Go version from go.dev"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Latest Go version from go.dev: $LATEST_GO_VERSION"
|
||||
echo "version=$LATEST_GO_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract version numbers (e.g., go1.26.0 -> 1.26.0)
|
||||
LATEST_VERSION_NUM=$(echo $LATEST_GO_VERSION | sed 's/^go//')
|
||||
echo "version_num=$LATEST_VERSION_NUM" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract major.minor version (e.g., 1.26.0 -> 1.26)
|
||||
LATEST_MAJOR_MINOR=$(echo $LATEST_VERSION_NUM | sed -E 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
echo "major_minor=$LATEST_MAJOR_MINOR" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Check current Go version
|
||||
id: current-version
|
||||
run: |
|
||||
CURRENT_VERSION=$(sed -n 's/.*go_sdk\.download(version = \"\([^\"]*\)\".*/\1/p' MODULE.bazel)
|
||||
|
||||
if [ -z "$CURRENT_VERSION" ]; then
|
||||
echo "Error: Could not extract Go version from MODULE.bazel"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Current Go version in MODULE.bazel: $CURRENT_VERSION"
|
||||
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract major.minor version
|
||||
CURRENT_MAJOR_MINOR=$(echo $CURRENT_VERSION | sed -E 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
echo "major_minor=$CURRENT_MAJOR_MINOR" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Compare versions
|
||||
id: compare
|
||||
run: |
|
||||
LATEST="${{ steps.fetch-version.outputs.version_num }}"
|
||||
CURRENT="${{ steps.current-version.outputs.version }}"
|
||||
|
||||
echo "Latest: $LATEST"
|
||||
echo "Current: $CURRENT"
|
||||
|
||||
if [ "$LATEST" = "$CURRENT" ]; then
|
||||
echo "Go version is up to date"
|
||||
echo "needs_update=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Go version needs update from $CURRENT to $LATEST"
|
||||
echo "needs_update=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Update Go version in files
|
||||
if: steps.compare.outputs.needs_update == 'true'
|
||||
run: |
|
||||
LATEST_VERSION_NUM="${{ steps.fetch-version.outputs.version_num }}"
|
||||
LATEST_MAJOR_MINOR="${{ steps.fetch-version.outputs.major_minor }}"
|
||||
CURRENT_VERSION="${{ steps.current-version.outputs.version }}"
|
||||
CURRENT_MAJOR_MINOR="${{ steps.current-version.outputs.major_minor }}"
|
||||
|
||||
echo "Updating from $CURRENT_VERSION to $LATEST_VERSION_NUM"
|
||||
|
||||
# Escape dots in current version strings for use in sed patterns
|
||||
CURRENT_VERSION_ESCAPED=$(echo "$CURRENT_VERSION" | sed 's/\./\\./g')
|
||||
CURRENT_MAJOR_MINOR_ESCAPED=$(echo "$CURRENT_MAJOR_MINOR" | sed 's/\./\\./g')
|
||||
|
||||
# Update MODULE.bazel
|
||||
sed -i "s/go_sdk\.download(version = \"$CURRENT_VERSION_ESCAPED\")/go_sdk.download(version = \"$LATEST_VERSION_NUM\")/" MODULE.bazel
|
||||
if ! grep -q "go_sdk.download(version = \"$LATEST_VERSION_NUM\")" MODULE.bazel; then
|
||||
echo "Error: Failed to update MODULE.bazel"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update go/extractor/go.mod
|
||||
if ! sed -i "s/^go $CURRENT_MAJOR_MINOR_ESCAPED\$/go $LATEST_MAJOR_MINOR/" go/extractor/go.mod; then
|
||||
echo "Warning: Failed to update go directive in go.mod"
|
||||
fi
|
||||
if ! sed -i "s/^toolchain go$CURRENT_VERSION_ESCAPED\$/toolchain go$LATEST_VERSION_NUM/" go/extractor/go.mod; then
|
||||
echo "Warning: Failed to update toolchain in go.mod"
|
||||
fi
|
||||
|
||||
# Update go/extractor/autobuilder/build-environment.go
|
||||
if ! sed -i "s/var maxGoVersion = util\.NewSemVer(\"$CURRENT_MAJOR_MINOR_ESCAPED\")/var maxGoVersion = util.NewSemVer(\"$LATEST_MAJOR_MINOR\")/" go/extractor/autobuilder/build-environment.go; then
|
||||
echo "Warning: Failed to update build-environment.go"
|
||||
fi
|
||||
|
||||
# Update go/actions/test/action.yml
|
||||
if ! sed -i "s/default: \"~$CURRENT_VERSION_ESCAPED\"/default: \"~$LATEST_VERSION_NUM\"/" go/actions/test/action.yml; then
|
||||
echo "Warning: Failed to update action.yml"
|
||||
fi
|
||||
|
||||
# Show what changed
|
||||
git diff
|
||||
|
||||
- name: Check for changes
|
||||
id: check-changes
|
||||
if: steps.compare.outputs.needs_update == 'true'
|
||||
run: |
|
||||
if git diff --quiet; then
|
||||
echo "No changes detected"
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Changes detected"
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Check for existing PR
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
id: check-pr
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
BRANCH_NAME="workflow/go-version-update"
|
||||
PR_NUMBER=$(gh pr list --head "$BRANCH_NAME" --state open --json number --jq '.[0].number')
|
||||
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
echo "Existing PR found: #$PR_NUMBER"
|
||||
echo "pr_exists=true" >> $GITHUB_OUTPUT
|
||||
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "No existing PR found"
|
||||
echo "pr_exists=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Commit and push changes
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
run: |
|
||||
BRANCH_NAME="workflow/go-version-update"
|
||||
LATEST_VERSION_NUM="${{ steps.fetch-version.outputs.version_num }}"
|
||||
LATEST_MAJOR_MINOR="${{ steps.fetch-version.outputs.major_minor }}"
|
||||
|
||||
# Create or switch to branch
|
||||
git checkout -B "$BRANCH_NAME"
|
||||
|
||||
# Stage and commit changes
|
||||
git add MODULE.bazel go/extractor/go.mod go/extractor/autobuilder/build-environment.go go/actions/test/action.yml
|
||||
git commit -m "Go: Update to $LATEST_VERSION_NUM"
|
||||
|
||||
# Push changes
|
||||
git push --force-with-lease origin "$BRANCH_NAME"
|
||||
|
||||
- name: Create or update PR
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
BRANCH_NAME="workflow/go-version-update"
|
||||
LATEST_VERSION_NUM="${{ steps.fetch-version.outputs.version_num }}"
|
||||
CURRENT_VERSION="${{ steps.current-version.outputs.version }}"
|
||||
|
||||
PR_TITLE="Go: Update to $LATEST_VERSION_NUM"
|
||||
|
||||
PR_BODY=$(cat <<EOF
|
||||
This PR updates Go from $CURRENT_VERSION to $LATEST_VERSION_NUM.
|
||||
|
||||
Updated files:
|
||||
- \`MODULE.bazel\` - go_sdk.download version
|
||||
- \`go/extractor/go.mod\` - go directive and toolchain
|
||||
- \`go/extractor/autobuilder/build-environment.go\` - maxGoVersion (only if MAJOR.MINOR changes)
|
||||
- \`go/actions/test/action.yml\` - default go-test-version
|
||||
|
||||
This PR was automatically created by the [Go version update workflow](https://github.com/${{ github.repository }}/blob/main/.github/workflows/go-version-update.yml).
|
||||
EOF
|
||||
)
|
||||
|
||||
if [ "${{ steps.check-pr.outputs.pr_exists }}" = "true" ]; then
|
||||
echo "Updating existing PR #${{ steps.check-pr.outputs.pr_number }}"
|
||||
gh pr edit "${{ steps.check-pr.outputs.pr_number }}" --title "$PR_TITLE" --body "$PR_BODY"
|
||||
else
|
||||
echo "Creating new PR"
|
||||
gh pr create \
|
||||
--title "$PR_TITLE" \
|
||||
--body "$PR_BODY" \
|
||||
--base main \
|
||||
--head "$BRANCH_NAME" \
|
||||
--label "Go"
|
||||
fi
|
||||
@@ -273,7 +273,7 @@ use_repo(
|
||||
)
|
||||
|
||||
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
|
||||
go_sdk.download(version = "1.26.4")
|
||||
go_sdk.download(version = "1.26.0")
|
||||
|
||||
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
|
||||
go_deps.from_file(go_mod = "//go/extractor:go.mod")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
description: Fix NameQualifier inconsistency
|
||||
compatibility: full
|
||||
@@ -1071,7 +1071,7 @@ class NullPointerType extends BuiltInType {
|
||||
* const float fa[40];
|
||||
* ```
|
||||
*/
|
||||
class DerivedType extends Type, NameQualifyingElement, @derivedtype {
|
||||
class DerivedType extends Type, @derivedtype {
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
override string getName() { derivedtypes(underlyingElement(this), result, _, _) }
|
||||
|
||||
@@ -61,12 +61,13 @@ private predicate discardElement(@element e) {
|
||||
// particular, been deleted), or the overlay has redefined the TRAP
|
||||
// file or tag it is in, or the overlay runner has re-extracted the same
|
||||
// source file (e.g. because a header it includes has changed).
|
||||
forall(@trap_or_tag t, string sourceFile |
|
||||
not exists(@trap_or_tag t |
|
||||
locallyInTrapOrTag(false, e, t) and
|
||||
locallyReachableTrapOrTag(false, sourceFile, t)
|
||||
|
|
||||
overlayChangedFiles(sourceFile) or
|
||||
locallyReachableTrapOrTag(true, _, t) or
|
||||
locallyReachableTrapOrTag(true, sourceFile, _)
|
||||
not locallyReachableTrapOrTag(true, _, t) and
|
||||
exists(string sourceFile |
|
||||
locallyReachableTrapOrTag(false, sourceFile, t) and
|
||||
not overlayChangedFiles(sourceFile) and
|
||||
not locallyReachableTrapOrTag(true, sourceFile, _)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1430,8 +1430,7 @@ specialnamequalifyingelements(
|
||||
@namequalifyingelement = @namespace
|
||||
| @specialnamequalifyingelement
|
||||
| @usertype
|
||||
| @decltype
|
||||
| @derivedtype;
|
||||
| @decltype;
|
||||
|
||||
namequalifiers(
|
||||
unique int id: @namequalifier,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
description: Fix NameQualifier inconsistency
|
||||
compatibility: full
|
||||
@@ -1,7 +1,3 @@
|
||||
| inconsistency2.cpp:3:3:3:5 | T:: | inconsistency2.cpp:3:3:3:6 | x | inconsistency2.cpp:2:20:2:20 | T |
|
||||
| inconsistency2.cpp:3:3:3:11 | const s:: | inconsistency2.cpp:3:3:3:6 | x | file://:0:0:0:0 | const s |
|
||||
| inconsistency.cpp:7:20:7:22 | S:: | inconsistency.cpp:7:20:7:23 | (int)... | inconsistency.cpp:4:8:4:8 | S |
|
||||
| inconsistency.cpp:7:20:7:22 | S:: | inconsistency.cpp:7:20:7:23 | A | inconsistency.cpp:4:8:4:8 | S |
|
||||
| name_qualifiers.cpp:29:7:29:8 | :: | name_qualifiers.cpp:29:7:29:9 | x | file://:0:0:0:0 | (global namespace) |
|
||||
| name_qualifiers.cpp:31:7:31:10 | N1:: | name_qualifiers.cpp:31:7:31:12 | nx | name_qualifiers.cpp:4:11:4:12 | N1 |
|
||||
| name_qualifiers.cpp:34:7:34:8 | :: | name_qualifiers.cpp:34:9:34:12 | N1:: | file://:0:0:0:0 | (global namespace) |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import cpp
|
||||
|
||||
from NameQualifier nq, Location l
|
||||
where l = nq.getQualifiedElement().getLocation()
|
||||
where
|
||||
l = nq.getQualifiedElement().getLocation() and
|
||||
l.getFile().getShortName() = "name_qualifiers"
|
||||
select nq, nq.getQualifiedElement(), nq.getQualifyingElement()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// This file is present to test whether name-qualifying an enum constant leads to a database inconsistency.
|
||||
|
||||
// As such, there is no QL part of the test.
|
||||
|
||||
struct S { enum E { A }; };
|
||||
|
||||
static void f() {
|
||||
static int f() {
|
||||
switch(0) { case S::A: break; }
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace {
|
||||
template <typename T> T f() {
|
||||
T::x;
|
||||
return {};
|
||||
}
|
||||
struct s {
|
||||
static int x;
|
||||
};
|
||||
struct t {
|
||||
s x = f<const s>();
|
||||
};
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
.. _codeql-cli-2.25.6:
|
||||
|
||||
==========================
|
||||
CodeQL 2.25.6 (2026-06-04)
|
||||
==========================
|
||||
|
||||
.. contents:: Contents
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog <https://github.blog/tag/code-scanning/>`__, `relevant GitHub Changelog updates <https://github.blog/changelog/label/application-security/>`__, `changes in the CodeQL extension for Visual Studio Code <https://marketplace.visualstudio.com/items/GitHub.vscode-codeql/changelog>`__, and the `CodeQL Action changelog <https://github.com/github/codeql-action/blob/main/CHANGELOG.md>`__.
|
||||
|
||||
Security Coverage
|
||||
-----------------
|
||||
|
||||
CodeQL 2.25.6 runs a total of 496 security queries when configured with the Default suite (covering 169 CWE). The Extended suite enables an additional 131 queries (covering 32 more CWE).
|
||||
|
||||
CodeQL CLI
|
||||
----------
|
||||
|
||||
Improvements
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* When the :code:`git` executable is available, CodeQL can now obtain configuration and queries from SHA-256 Git repositories, and infer Git metadata about them.
|
||||
|
||||
Miscellaneous
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
* The build of Eclipse Temurin OpenJDK that is used to run the CodeQL CLI has been updated to version 21.0.11.
|
||||
|
||||
Query Packs
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Adjusted (minor) help file descriptions for queries: :code:`actions/untrusted-checkout/critical`, :code:`actions/untrusted-checkout/high`, :code:`actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
|
||||
Major Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Adjusted :code:`actions/untrusted-checkout/critical` to align more with other untrusted resource queries, where the alert location is the location where the artifact is obtained from (the checkout point). This aligns with the other 2 related queries. This will cause the same alerts to re-open for closed alerts of this query.
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Altered the alert message for clarity for queries: :code:`actions/untrusted-checkout/critical`, :code:`actions/untrusted-checkout/high`.
|
||||
* The :code:`actions/unpinned-tag` query now recognizes 64-character SHA-256 commit hashes as properly pinned references, in addition to 40-character SHA-1 hashes.
|
||||
|
||||
Query Metadata Changes
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Reversed adjustment of the name of :code:`actions/untrusted-checkout/high`, but kept the portion of the previous change for the word "trusted" to "privileged". Added a missing "a" to phrasing in :code:`actions/untrusted-checkout/high` and :code:`actions/untrusted-checkout/medium`.
|
||||
|
||||
Language Libraries
|
||||
------------------
|
||||
|
||||
Major Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Swift
|
||||
"""""
|
||||
|
||||
* Upgraded to allow analysis of Swift 6.3.2.
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added flow source models for :code:`scanf_s` and related functions.
|
||||
* Added a :code:`Call` column to :code:`LocalFlowSourceFunction::hasLocalFlowSource` and :code:`RemoteFlowSourceFunction::hasRemoteFlowSource`. The old predicates without a :code:`Call` column continue to be supported.
|
||||
|
||||
C#
|
||||
""
|
||||
|
||||
* Full support for C# 14 / .NET 10. All new language features are now supported by the extractor. The QL library and data flow analysis now support the new C# 14 language constructs and include generated Models as Data (MaD) models for the .NET 10 runtime.
|
||||
* C# 14: Added support for user-defined instance increment/decrement operators.
|
||||
|
||||
Java/Kotlin
|
||||
"""""""""""
|
||||
|
||||
* Added LLM-generated source and sink models for :code:`org.apache.avro`.
|
||||
|
||||
JavaScript/TypeScript
|
||||
"""""""""""""""""""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`js/clear-text-logging`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
Python
|
||||
""""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`py/clear-text-logging-sensitive-data`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
Swift
|
||||
"""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`swift/cleartext-logging`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like :code:`^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
|
||||
Rust
|
||||
""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`rust/cleartext-logging`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
Deprecated APIs
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* The :code:`UsingAliasTypedefType` class has been deprecated. Use :code:`TypeAliasType` instead.
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added a :code:`getOriginalTemplate` predicate to :code:`TemplateClass`, :code:`TemplateFunction`, :code:`TemplateVariable`, and :code:`AliasTemplateType`, which yields the class member template the template was generated from. The predicates only have results for templates that are members of class template instantiations.
|
||||
* Added :code:`AliasTemplateType` and :code:`AliasTemplateInstantiationType` classes, representing C++ alias templates and their instantiations.
|
||||
@@ -11,7 +11,6 @@ A list of queries for each suite and language `is available here <https://docs.g
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
codeql-cli-2.25.6
|
||||
codeql-cli-2.25.5
|
||||
codeql-cli-2.25.4
|
||||
codeql-cli-2.25.3
|
||||
|
||||
@@ -4,7 +4,7 @@ inputs:
|
||||
go-test-version:
|
||||
description: Which Go version to use for running the tests
|
||||
required: false
|
||||
default: "~1.26.4"
|
||||
default: "~1.26.0"
|
||||
run-code-checks:
|
||||
description: Whether to run formatting, code and qhelp generation checks
|
||||
required: false
|
||||
|
||||
@@ -2,14 +2,14 @@ module github.com/github/codeql-go/extractor
|
||||
|
||||
go 1.26
|
||||
|
||||
toolchain go1.26.4
|
||||
toolchain go1.26.0
|
||||
|
||||
// when updating this, run
|
||||
// bazel run @rules_go//go -- mod tidy
|
||||
// when adding or removing dependencies, run
|
||||
// bazel mod tidy
|
||||
require (
|
||||
golang.org/x/mod v0.37.0
|
||||
golang.org/x/mod v0.36.0
|
||||
golang.org/x/tools v0.45.0
|
||||
)
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
||||
golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4=
|
||||
golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* @name Web Cache Deception
|
||||
* @description A caching system has been detected on the application and is vulnerable to web cache deception. By manipulating the URL it is possible to force the application to cache pages that are only accessible by an authenticated user. Once cached, these pages can be accessed by an unauthenticated user.
|
||||
* @kind problem
|
||||
|
||||
@@ -54,31 +54,31 @@ func main() {}
|
||||
// bad is an example of a bad implementation
|
||||
func (ld *Ldap) bad(req *http.Request) {
|
||||
// ...
|
||||
untrusted := req.UserAgent() // $ Source
|
||||
untrusted := req.UserAgent()
|
||||
goldap.NewSearchRequest(
|
||||
untrusted, // $ Alert // BAD: untrusted dn
|
||||
untrusted, // BAD: untrusted dn
|
||||
goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
|
||||
"(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter
|
||||
[]string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute
|
||||
"(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter
|
||||
[]string{"dn", "cn", untrusted}, // BAD: untrusted attribute
|
||||
nil,
|
||||
)
|
||||
goldapv3.NewSearchRequest(
|
||||
untrusted, // $ Alert // BAD: untrusted dn
|
||||
untrusted, // BAD: untrusted dn
|
||||
goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
|
||||
"(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter
|
||||
[]string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute
|
||||
"(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter
|
||||
[]string{"dn", "cn", untrusted}, // BAD: untrusted attribute
|
||||
nil,
|
||||
)
|
||||
gopkgldapv2.NewSearchRequest(
|
||||
untrusted, // $ Alert // BAD: untrusted dn
|
||||
untrusted, // BAD: untrusted dn
|
||||
goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
|
||||
"(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter
|
||||
[]string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute
|
||||
"(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter
|
||||
[]string{"dn", "cn", untrusted}, // BAD: untrusted attribute
|
||||
nil,
|
||||
)
|
||||
client := &ldapclient.LDAPClient{}
|
||||
client.Authenticate(untrusted, "123456") // $ Alert // BAD: untrusted filter
|
||||
client.GetGroupsOfUser(untrusted) // $ Alert // BAD: untrusted filter
|
||||
client.Authenticate(untrusted, "123456") // BAD: untrusted filter
|
||||
client.GetGroupsOfUser(untrusted) // BAD: untrusted filter
|
||||
// ...
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: experimental/CWE-090/LDAPInjection.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: experimental/CWE-203/Timing.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -12,9 +12,9 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
secret := "MySuperSecretPasscode"
|
||||
secretHeader := "X-Secret"
|
||||
|
||||
headerSecret := req.Header.Get(secretHeader) // $ Source
|
||||
headerSecret := req.Header.Get(secretHeader)
|
||||
secretStr := string(secret)
|
||||
if len(headerSecret) != 0 && headerSecret != secretStr { // $ Alert
|
||||
if len(headerSecret) != 0 && headerSecret != secretStr {
|
||||
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
|
||||
}
|
||||
return nil, nil
|
||||
@@ -25,9 +25,9 @@ func bad2(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
secret := "MySuperSecretPasscode"
|
||||
secretHeader := "X-Secret"
|
||||
|
||||
headerSecret := req.Header.Get(secretHeader) // $ Source
|
||||
headerSecret := req.Header.Get(secretHeader)
|
||||
secretStr := string(secret)
|
||||
if len(headerSecret) != 0 && strings.Compare(headerSecret, secretStr) != 0 { // $ Alert
|
||||
if len(headerSecret) != 0 && strings.Compare(headerSecret, secretStr) != 0 {
|
||||
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
|
||||
}
|
||||
return nil, nil
|
||||
@@ -38,8 +38,8 @@ func bad4(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
secret := "MySuperSecretPasscode"
|
||||
secretHeader := "X-Secret"
|
||||
|
||||
headerSecret := req.Header.Get(secretHeader) // $ Source
|
||||
if len(secret) != 0 && headerSecret != "SecretStringLiteral" { // $ Alert
|
||||
headerSecret := req.Header.Get(secretHeader)
|
||||
if len(secret) != 0 && headerSecret != "SecretStringLiteral" {
|
||||
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
|
||||
}
|
||||
return nil, nil
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: experimental/CWE-285/PamAuthBypass.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
experimental/CWE-285/PamAuthBypass.ql
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
func bad() error {
|
||||
t, _ := pam.StartFunc("", "", func(s pam.Style, msg string) (string, error) {
|
||||
return "", nil
|
||||
}) // $ Alert
|
||||
})
|
||||
return t.Authenticate(0)
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
ldapServer := "ldap.example.com"
|
||||
ldapPort := 389
|
||||
bindDN := "cn=admin,dc=example,dc=com"
|
||||
bindPassword := req.URL.Query()["password"][0] // $ Source
|
||||
bindPassword := req.URL.Query()["password"][0]
|
||||
|
||||
// Connect to the LDAP server
|
||||
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
@@ -25,7 +25,7 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
defer l.Close()
|
||||
|
||||
// BAD: user input is not sanetized
|
||||
err = l.Bind(bindDN, bindPassword) // $ Alert
|
||||
err = l.Bind(bindDN, bindPassword)
|
||||
if err != nil {
|
||||
return fmt.Errorf("LDAP bind failed: %v", err), err
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func bad2(req *http.Request) {
|
||||
ldapPort := 389
|
||||
bindDN := "cn=admin,dc=example,dc=com"
|
||||
// BAD : empty password
|
||||
bindPassword := "" // $ Source
|
||||
bindPassword := ""
|
||||
|
||||
// Connect to the LDAP server
|
||||
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
@@ -94,7 +94,7 @@ func bad2(req *http.Request) {
|
||||
defer l.Close()
|
||||
|
||||
// BAD : bindPassword is empty
|
||||
err = l.Bind(bindDN, bindPassword) // $ Alert
|
||||
err = l.Bind(bindDN, bindPassword)
|
||||
if err != nil {
|
||||
log.Fatalf("LDAP bind failed: %v", err)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: experimental/CWE-287/ImproperLdapAuth.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
#select
|
||||
| go-jose.v3.go:24:32:24:37 | JwtKey | go-jose.v3.go:13:21:13:33 | "AllYourBase" | go-jose.v3.go:24:32:24:37 | JwtKey | This $@. | go-jose.v3.go:13:21:13:33 | "AllYourBase" | Constant Key is used as JWT Secret key |
|
||||
| golang-jwt-v5.go:27:9:27:15 | JwtKey1 | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | golang-jwt-v5.go:27:9:27:15 | JwtKey1 | This $@. | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | Constant Key is used as JWT Secret key |
|
||||
edges
|
||||
| go-jose.v3.go:13:14:13:34 | type conversion | go-jose.v3.go:24:32:24:37 | JwtKey | provenance | |
|
||||
| go-jose.v3.go:13:21:13:33 | "AllYourBase" | go-jose.v3.go:13:14:13:34 | type conversion | provenance | |
|
||||
@@ -14,3 +11,6 @@ nodes
|
||||
| golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | semmle.label | "AllYourBase" |
|
||||
| golang-jwt-v5.go:27:9:27:15 | JwtKey1 | semmle.label | JwtKey1 |
|
||||
subpaths
|
||||
#select
|
||||
| go-jose.v3.go:24:32:24:37 | JwtKey | go-jose.v3.go:13:21:13:33 | "AllYourBase" | go-jose.v3.go:24:32:24:37 | JwtKey | This $@. | go-jose.v3.go:13:21:13:33 | "AllYourBase" | Constant Key is used as JWT Secret key |
|
||||
| golang-jwt-v5.go:27:9:27:15 | JwtKey1 | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | golang-jwt-v5.go:27:9:27:15 | JwtKey1 | This $@. | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | Constant Key is used as JWT Secret key |
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: experimental/CWE-321-V2/HardCodedKeys.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
experimental/CWE-321-V2/HardCodedKeys.ql
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
// NOT OK
|
||||
var JwtKey = []byte("AllYourBase") // $ Source
|
||||
var JwtKey = []byte("AllYourBase")
|
||||
|
||||
func main2(r *http.Request) {
|
||||
signedToken := r.URL.Query().Get("signedToken")
|
||||
@@ -21,7 +21,7 @@ func verifyJWT(signedToken string) {
|
||||
fmt.Println("verifying JWT")
|
||||
DecodedToken, _ := jwt.ParseSigned(signedToken)
|
||||
out := CustomerInfo{}
|
||||
if err := DecodedToken.Claims(JwtKey, &out); err != nil { // $ Alert
|
||||
if err := DecodedToken.Claims(JwtKey, &out); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("%v\n", out)
|
||||
|
||||
@@ -16,7 +16,7 @@ type CustomerInfo struct {
|
||||
}
|
||||
|
||||
// BAD constant key
|
||||
var JwtKey1 = []byte("AllYourBase") // $ Source
|
||||
var JwtKey1 = []byte("AllYourBase")
|
||||
|
||||
func main1(r *http.Request) {
|
||||
signedToken := r.URL.Query().Get("signedToken")
|
||||
@@ -24,7 +24,7 @@ func main1(r *http.Request) {
|
||||
}
|
||||
|
||||
func LoadJwtKey(token *jwt.Token) (interface{}, error) {
|
||||
return JwtKey1, nil // $ Alert
|
||||
return JwtKey1, nil
|
||||
}
|
||||
|
||||
func verifyJWT_golangjwt(signedToken string) {
|
||||
|
||||
@@ -7,37 +7,37 @@ import (
|
||||
)
|
||||
|
||||
func myHandler1(w http.ResponseWriter, r *http.Request) {
|
||||
param1 := r.URL.Query()["param1"][0] // $ Source
|
||||
param1 := r.URL.Query()["param1"][0]
|
||||
value, _ := strconv.Atoi(param1)
|
||||
out := 1337 / value // $ Alert
|
||||
out := 1337 / value
|
||||
fmt.Println(out)
|
||||
}
|
||||
|
||||
func myHandler2(w http.ResponseWriter, r *http.Request) {
|
||||
param1 := r.URL.Query()["param1"][0] // $ Source
|
||||
param1 := r.URL.Query()["param1"][0]
|
||||
value := int(param1[0])
|
||||
out := 1337 / value // $ Alert
|
||||
out := 1337 / value
|
||||
fmt.Println(out)
|
||||
}
|
||||
|
||||
func myHandler3(w http.ResponseWriter, r *http.Request) {
|
||||
param1 := r.URL.Query()["param1"][0] // $ Source
|
||||
param1 := r.URL.Query()["param1"][0]
|
||||
value, _ := strconv.ParseInt(param1, 10, 64)
|
||||
out := 1337 / value // $ Alert
|
||||
out := 1337 / value
|
||||
fmt.Println(out)
|
||||
}
|
||||
|
||||
func myHandler4(w http.ResponseWriter, r *http.Request) {
|
||||
param1 := r.URL.Query()["param1"][0] // $ Source
|
||||
param1 := r.URL.Query()["param1"][0]
|
||||
value, _ := strconv.ParseFloat(param1, 32)
|
||||
out := 1337 / value // $ Alert
|
||||
out := 1337 / value
|
||||
fmt.Println(out)
|
||||
}
|
||||
|
||||
func myHandler5(w http.ResponseWriter, r *http.Request) {
|
||||
param1 := r.URL.Query()["param1"][0] // $ Source
|
||||
param1 := r.URL.Query()["param1"][0]
|
||||
value, _ := strconv.ParseUint(param1, 10, 64)
|
||||
out := 1337 / value // $ Alert
|
||||
out := 1337 / value
|
||||
fmt.Println(out)
|
||||
}
|
||||
|
||||
@@ -51,10 +51,10 @@ func myHandler6(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func myHandler7(w http.ResponseWriter, r *http.Request) {
|
||||
param1 := r.URL.Query()["param1"][0] // $ Source
|
||||
param1 := r.URL.Query()["param1"][0]
|
||||
value := int(param1[0])
|
||||
if value >= 0 {
|
||||
out := 1337 / value // $ Alert
|
||||
out := 1337 / value
|
||||
fmt.Println(out)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: experimental/CWE-369/DivideByZero.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
#select
|
||||
| DatabaseCallInLoop.go:9:3:9:41 | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | This calls call to First in a $@. | DatabaseCallInLoop.go:7:2:11:2 | range statement | loop |
|
||||
| test.go:11:2:11:13 | call to Take | test.go:20:2:22:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:20:2:22:2 | for statement | loop |
|
||||
| test.go:11:2:11:13 | call to Take | test.go:24:2:26:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:24:2:26:2 | for statement | loop |
|
||||
edges
|
||||
| DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First |
|
||||
| test.go:10:1:12:1 | function declaration | test.go:11:2:11:13 | call to Take |
|
||||
@@ -11,3 +7,7 @@ edges
|
||||
| test.go:21:3:21:14 | call to runQuery | test.go:10:1:12:1 | function declaration |
|
||||
| test.go:24:2:26:2 | for statement | test.go:25:3:25:17 | call to runRunQuery |
|
||||
| test.go:25:3:25:17 | call to runRunQuery | test.go:14:1:16:1 | function declaration |
|
||||
#select
|
||||
| DatabaseCallInLoop.go:9:3:9:41 | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | This calls call to First in a $@. | DatabaseCallInLoop.go:7:2:11:2 | range statement | loop |
|
||||
| test.go:11:2:11:13 | call to Take | test.go:20:2:22:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:20:2:22:2 | for statement | loop |
|
||||
| test.go:11:2:11:13 | call to Take | test.go:24:2:26:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:24:2:26:2 | for statement | loop |
|
||||
|
||||
@@ -6,8 +6,8 @@ func getUsers(db *gorm.DB, names []string) []User {
|
||||
res := make([]User, 0, len(names))
|
||||
for _, name := range names {
|
||||
var user User
|
||||
db.Where("name = ?", name).First(&user) // $ Alert
|
||||
db.Where("name = ?", name).First(&user)
|
||||
res = append(res, user)
|
||||
} // $ Source
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: experimental/CWE-400/DatabaseCallInLoop.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
experimental/CWE-400/DatabaseCallInLoop.ql
|
||||
|
||||
@@ -8,7 +8,7 @@ type User struct {
|
||||
}
|
||||
|
||||
func runQuery(db *gorm.DB) {
|
||||
db.Take(nil) // $ Alert
|
||||
db.Take(nil)
|
||||
}
|
||||
|
||||
func runRunQuery(db *gorm.DB) {
|
||||
@@ -19,9 +19,9 @@ func main() {
|
||||
var db *gorm.DB
|
||||
for i := 0; i < 10; i++ {
|
||||
runQuery(db)
|
||||
} // $ Source
|
||||
}
|
||||
|
||||
for i := 10; i > 0; i-- {
|
||||
runRunQuery(db)
|
||||
} // $ Source
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: experimental/CWE-522-DecompressionBombs/DecompressionBombs.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -56,41 +56,41 @@ func main() {
|
||||
func DecompressHandler(w http.ResponseWriter, request *http.Request) {
|
||||
GZipOpenReaderSafe(request.PostFormValue("test"))
|
||||
ZipOpenReaderSafe(request.PostFormValue("test"))
|
||||
ZipOpenReader(request.FormValue("filepath")) // $ Source
|
||||
ZipNewReader(request.Body) // $ Source
|
||||
ZipNewReaderKlauspost(request.Body) // $ Source
|
||||
Bzip2Dsnet(request.Body) // $ Source
|
||||
ZipOpenReader(request.FormValue("filepath"))
|
||||
ZipNewReader(request.Body)
|
||||
ZipNewReaderKlauspost(request.Body)
|
||||
Bzip2Dsnet(request.Body)
|
||||
Bzip2DsnetSafe(request.Body)
|
||||
Bzip2(request.Body) // $ Source
|
||||
Bzip2(request.Body)
|
||||
Bzip2Safe(request.Body)
|
||||
Flate(request.Body) // $ Source
|
||||
Flate(request.Body)
|
||||
FlateSafe(request.Body)
|
||||
FlateKlauspost(request.Body) // $ Source
|
||||
FlateKlauspost(request.Body)
|
||||
FlateKlauspostSafe(request.Body)
|
||||
FlateDsnet(request.Body) // $ Source
|
||||
FlateDsnet(request.Body)
|
||||
FlateDsnetSafe(request.Body)
|
||||
ZlibKlauspost(request.Body) // $ Source
|
||||
ZlibKlauspost(request.Body)
|
||||
ZlibKlauspostSafe(request.Body)
|
||||
Zlib(request.Body) // $ Source
|
||||
Zlib(request.Body)
|
||||
ZlibSafe(request.Body)
|
||||
Snappy(request.Body) // $ Source
|
||||
Snappy(request.Body)
|
||||
SnappySafe(request.Body)
|
||||
SnappyKlauspost(request.Body) // $ Source
|
||||
SnappyKlauspost(request.Body)
|
||||
SnappyKlauspostSafe(request.Body)
|
||||
S2(request.Body) // $ Source
|
||||
S2(request.Body)
|
||||
S2Safe(request.Body)
|
||||
Gzip(request.Body) // $ Source
|
||||
Gzip(request.Body)
|
||||
GzipSafe(request.Body)
|
||||
GZipIoReader(request.Body, "dest") // $ Source
|
||||
GzipKlauspost(request.Body) // $ Source
|
||||
GZipIoReader(request.Body, "dest")
|
||||
GzipKlauspost(request.Body)
|
||||
GzipKlauspostSafe(request.Body)
|
||||
PzipKlauspost(request.Body) // $ Source
|
||||
PzipKlauspost(request.Body)
|
||||
PzipKlauspostSafe(request.Body)
|
||||
Zstd_Klauspost(request.Body) // $ Source
|
||||
Zstd_Klauspost(request.Body)
|
||||
Zstd_KlauspostSafe(request.Body)
|
||||
Zstd_DataDog(request.Body) // $ Source
|
||||
Zstd_DataDog(request.Body)
|
||||
Zstd_DataDogSafe(request.Body)
|
||||
Xz(request.Body) // $ Source
|
||||
Xz(request.Body)
|
||||
XzSafe(request.Body)
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ func ZipOpenReader(filename string) {
|
||||
for _, f := range zipReader.File {
|
||||
rc, _ := f.Open()
|
||||
for {
|
||||
result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" Alert
|
||||
result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc"
|
||||
if result == 0 {
|
||||
_ = rc.Close()
|
||||
break
|
||||
@@ -144,7 +144,7 @@ func ZipOpenReader(filename string) {
|
||||
for _, f := range zipKlauspostReader.File {
|
||||
rc, _ := f.Open()
|
||||
for {
|
||||
result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" Alert
|
||||
result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc"
|
||||
if result == 0 {
|
||||
_ = rc.Close()
|
||||
break
|
||||
@@ -161,7 +161,7 @@ func ZipNewReader(file io.Reader) {
|
||||
for _, file := range zipReader.File {
|
||||
fileWriter := bytes.NewBuffer([]byte{})
|
||||
fileReaderCloser, _ := file.Open()
|
||||
result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" Alert
|
||||
result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser"
|
||||
fmt.Print(result)
|
||||
}
|
||||
}
|
||||
@@ -173,7 +173,7 @@ func ZipNewReaderKlauspost(file io.Reader) {
|
||||
fileWriter := bytes.NewBuffer([]byte{})
|
||||
// file.OpenRaw()
|
||||
fileReaderCloser, _ := file.Open()
|
||||
result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" Alert
|
||||
result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser"
|
||||
fmt.Print(result)
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@ func Bzip2Dsnet(file io.Reader) {
|
||||
|
||||
bzip2Reader, _ := bzip2Dsnet.NewReader(file, &bzip2Dsnet.ReaderConfig{})
|
||||
var out []byte = make([]byte, 70)
|
||||
bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" Alert
|
||||
bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader"
|
||||
tarRead = tar.NewReader(bzip2Reader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -210,7 +210,7 @@ func Bzip2(file io.Reader) {
|
||||
|
||||
bzip2Reader := bzip2.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" Alert
|
||||
bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader"
|
||||
tarRead = tar.NewReader(bzip2Reader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -235,7 +235,7 @@ func Flate(file io.Reader) {
|
||||
|
||||
flateReader := flate.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
flateReader.Read(out) // $ hasValueFlow="flateReader" Alert
|
||||
flateReader.Read(out) // $ hasValueFlow="flateReader"
|
||||
tarRead = tar.NewReader(flateReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -260,7 +260,7 @@ func FlateKlauspost(file io.Reader) {
|
||||
|
||||
flateReader := flateKlauspost.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
flateReader.Read(out) // $ hasValueFlow="flateReader" Alert
|
||||
flateReader.Read(out) // $ hasValueFlow="flateReader"
|
||||
tarRead = tar.NewReader(flateReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -285,7 +285,7 @@ func FlateDsnet(file io.Reader) {
|
||||
|
||||
flateReader, _ := flateDsnet.NewReader(file, &flateDsnet.ReaderConfig{})
|
||||
var out []byte = make([]byte, 70)
|
||||
flateReader.Read(out) // $ hasValueFlow="flateReader" Alert
|
||||
flateReader.Read(out) // $ hasValueFlow="flateReader"
|
||||
tarRead = tar.NewReader(flateReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -310,7 +310,7 @@ func ZlibKlauspost(file io.Reader) {
|
||||
|
||||
zlibReader, _ := zlibKlauspost.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
zlibReader.Read(out) // $ hasValueFlow="zlibReader" Alert
|
||||
zlibReader.Read(out) // $ hasValueFlow="zlibReader"
|
||||
tarRead = tar.NewReader(zlibReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -335,7 +335,7 @@ func Zlib(file io.Reader) {
|
||||
|
||||
zlibReader, _ := zlib.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
zlibReader.Read(out) // $ hasValueFlow="zlibReader" Alert
|
||||
zlibReader.Read(out) // $ hasValueFlow="zlibReader"
|
||||
tarRead = tar.NewReader(zlibReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -360,8 +360,8 @@ func Snappy(file io.Reader) {
|
||||
|
||||
snappyReader := snappy.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
snappyReader.Read(out) // $ hasValueFlow="snappyReader" Alert
|
||||
snappyReader.ReadByte() // $ hasValueFlow="snappyReader" Alert
|
||||
snappyReader.Read(out) // $ hasValueFlow="snappyReader"
|
||||
snappyReader.ReadByte() // $ hasValueFlow="snappyReader"
|
||||
tarRead = tar.NewReader(snappyReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -386,10 +386,10 @@ func SnappyKlauspost(file io.Reader) {
|
||||
|
||||
snappyReader := snappyKlauspost.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
snappyReader.Read(out) // $ hasValueFlow="snappyReader" Alert
|
||||
snappyReader.Read(out) // $ hasValueFlow="snappyReader"
|
||||
var buf bytes.Buffer
|
||||
snappyReader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="snappyReader" Alert
|
||||
snappyReader.ReadByte() // $ hasValueFlow="snappyReader" Alert
|
||||
snappyReader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="snappyReader"
|
||||
snappyReader.ReadByte() // $ hasValueFlow="snappyReader"
|
||||
tarRead = tar.NewReader(snappyReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -414,10 +414,10 @@ func S2(file io.Reader) {
|
||||
|
||||
s2Reader := s2.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
s2Reader.Read(out) // $ hasValueFlow="s2Reader" Alert
|
||||
s2Reader.ReadByte() // $ hasValueFlow="s2Reader" Alert
|
||||
s2Reader.Read(out) // $ hasValueFlow="s2Reader"
|
||||
s2Reader.ReadByte() // $ hasValueFlow="s2Reader"
|
||||
var buf bytes.Buffer
|
||||
s2Reader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="s2Reader" Alert
|
||||
s2Reader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="s2Reader"
|
||||
tarRead = tar.NewReader(s2Reader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -442,14 +442,14 @@ func GZipIoReader(src io.Reader, dst string) {
|
||||
dstF, _ := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
|
||||
defer dstF.Close()
|
||||
newSrc := io.Reader(gzipReader)
|
||||
_, _ = io.Copy(dstF, newSrc) // $ hasValueFlow="newSrc" Alert
|
||||
_, _ = io.Copy(dstF, newSrc) // $ hasValueFlow="newSrc"
|
||||
}
|
||||
func Gzip(file io.Reader) {
|
||||
var tarRead *tar.Reader
|
||||
|
||||
gzipReader, _ := gzip.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
gzipReader.Read(out) // $ hasValueFlow="gzipReader" Alert
|
||||
gzipReader.Read(out) // $ hasValueFlow="gzipReader"
|
||||
tarRead = tar.NewReader(gzipReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -474,9 +474,9 @@ func GzipKlauspost(file io.Reader) {
|
||||
|
||||
gzipReader, _ := gzipKlauspost.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
gzipReader.Read(out) // $ hasValueFlow="gzipReader" Alert
|
||||
gzipReader.Read(out) // $ hasValueFlow="gzipReader"
|
||||
var buf bytes.Buffer
|
||||
gzipReader.WriteTo(&buf) // $ hasValueFlow="gzipReader" Alert
|
||||
gzipReader.WriteTo(&buf) // $ hasValueFlow="gzipReader"
|
||||
tarRead = tar.NewReader(gzipReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -501,9 +501,9 @@ func PzipKlauspost(file io.Reader) {
|
||||
|
||||
pgzipReader, _ := pgzipKlauspost.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
pgzipReader.Read(out) // $ hasValueFlow="pgzipReader" Alert
|
||||
pgzipReader.Read(out) // $ hasValueFlow="pgzipReader"
|
||||
var buf bytes.Buffer
|
||||
pgzipReader.WriteTo(&buf) // $ hasValueFlow="pgzipReader" Alert
|
||||
pgzipReader.WriteTo(&buf) // $ hasValueFlow="pgzipReader"
|
||||
tarRead = tar.NewReader(pgzipReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -528,11 +528,11 @@ func Zstd_Klauspost(file io.Reader) {
|
||||
|
||||
zstdReader, _ := zstdKlauspost.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
zstdReader.Read(out) // $ hasValueFlow="zstdReader" Alert
|
||||
zstdReader.Read(out) // $ hasValueFlow="zstdReader"
|
||||
var buf bytes.Buffer
|
||||
zstdReader.WriteTo(&buf) // $ hasValueFlow="zstdReader" Alert
|
||||
zstdReader.WriteTo(&buf) // $ hasValueFlow="zstdReader"
|
||||
var src []byte
|
||||
zstdReader.DecodeAll(src, nil) // $ hasValueFlow="zstdReader" Alert
|
||||
zstdReader.DecodeAll(src, nil) // $ hasValueFlow="zstdReader"
|
||||
tarRead = tar.NewReader(zstdReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -557,7 +557,7 @@ func Zstd_DataDog(file io.Reader) {
|
||||
|
||||
zstdReader := zstdDataDog.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
zstdReader.Read(out) // $ hasValueFlow="zstdReader" Alert
|
||||
zstdReader.Read(out) // $ hasValueFlow="zstdReader"
|
||||
tarRead = tar.NewReader(zstdReader)
|
||||
|
||||
TarDecompressor(tarRead)
|
||||
@@ -582,7 +582,7 @@ func Xz(file io.Reader) {
|
||||
|
||||
xzReader, _ := xz.NewReader(file)
|
||||
var out []byte = make([]byte, 70)
|
||||
xzReader.Read(out) // $ hasValueFlow="xzReader" Alert
|
||||
xzReader.Read(out) // $ hasValueFlow="xzReader"
|
||||
tarRead = tar.NewReader(xzReader)
|
||||
fmt.Println(io.SeekStart)
|
||||
|
||||
@@ -618,7 +618,7 @@ func TarDecompressor(tarRead *tar.Reader) {
|
||||
if cur.Typeflag != tar.TypeReg {
|
||||
continue
|
||||
}
|
||||
data, _ := io.ReadAll(tarRead) // $ hasValueFlow="tarRead" Alert
|
||||
data, _ := io.ReadAll(tarRead) // $ hasValueFlow="tarRead"
|
||||
files[cur.Name] = &fstest.MapFile{Data: data}
|
||||
}
|
||||
fmt.Print(files)
|
||||
@@ -626,7 +626,7 @@ func TarDecompressor(tarRead *tar.Reader) {
|
||||
|
||||
func TarDecompressor2(tarRead *tar.Reader) {
|
||||
var tarOut []byte = make([]byte, 70)
|
||||
tarRead.Read(tarOut) // $ hasValueFlow="tarRead" Alert
|
||||
tarRead.Read(tarOut) // $ hasValueFlow="tarRead"
|
||||
fmt.Println("do sth with output:", tarOut)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: experimental/CWE-525/WebCacheDeception.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
experimental/CWE-525/WebCacheDeception.ql
|
||||
@@ -79,7 +79,7 @@ func badRoutingNet() {
|
||||
|
||||
http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/"))))
|
||||
|
||||
http.HandleFunc("/adminusers/", ShowAdminPageCache) // $ Alert
|
||||
http.HandleFunc("/adminusers/", ShowAdminPageCache)
|
||||
err := http.ListenAndServe(":1337", nil)
|
||||
if err != nil {
|
||||
log.Fatal("ListenAndServe: ", err)
|
||||
|
||||
@@ -12,12 +12,12 @@ func badRouting() {
|
||||
log.Println("We are logging in Golang!")
|
||||
|
||||
// GET /api/register
|
||||
app.Get("/api/*", func(c *fiber.Ctx) error { // $ Alert
|
||||
app.Get("/api/*", func(c *fiber.Ctx) error {
|
||||
msg := fmt.Sprintf("✋")
|
||||
return c.SendString(msg) // => ✋ register
|
||||
})
|
||||
|
||||
app.Post("/api/*", func(c *fiber.Ctx) error { // $ Alert
|
||||
app.Post("/api/*", func(c *fiber.Ctx) error {
|
||||
msg := fmt.Sprintf("✋")
|
||||
return c.SendString(msg) // => ✋ register
|
||||
})
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
func badRoutingChi() {
|
||||
r := chi.NewRouter()
|
||||
r.Use(middleware.Logger)
|
||||
r.Get("/*", func(w http.ResponseWriter, r *http.Request) { // $ Alert
|
||||
r.Get("/*", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("welcome"))
|
||||
})
|
||||
http.ListenAndServe(":3000", r)
|
||||
|
||||
@@ -18,7 +18,7 @@ func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
|
||||
func badHTTPRouter() {
|
||||
router := httprouter.New()
|
||||
router.GET("/test/*test", Index) // $ Alert
|
||||
router.GET("/test/*test", Index)
|
||||
router.GET("/hello/:name", Hello)
|
||||
|
||||
log.Fatal(http.ListenAndServe(":8082", router))
|
||||
|
||||
@@ -23,10 +23,10 @@ func good() (interface{}, error) {
|
||||
}
|
||||
|
||||
func bad() interface{} {
|
||||
name2 := os.Args[1:] // $ Source[go/dsn-injection-local]
|
||||
name2 := os.Args[1:]
|
||||
// This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
|
||||
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name2[0])
|
||||
db, _ := sql.Open("mysql", dbDSN) // $ Alert[go/dsn-injection-local]
|
||||
db, _ := sql.Open("mysql", dbDSN)
|
||||
return db
|
||||
}
|
||||
|
||||
@@ -44,10 +44,10 @@ func good2(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
}
|
||||
|
||||
func bad2(w http.ResponseWriter, req *http.Request) interface{} {
|
||||
name := req.FormValue("name") // $ Source[go/dsn-injection]
|
||||
name := req.FormValue("name")
|
||||
// This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
|
||||
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name)
|
||||
db, _ := sql.Open("mysql", dbDSN) // $ Alert[go/dsn-injection]
|
||||
db, _ := sql.Open("mysql", dbDSN)
|
||||
return db
|
||||
}
|
||||
|
||||
@@ -60,12 +60,12 @@ func (Config) Parse([]string) error { return nil }
|
||||
|
||||
func RegexFuncModelTest(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
cfg := NewConfig()
|
||||
err := cfg.Parse(os.Args[1:]) // $ Source[go/dsn-injection-local] // This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
|
||||
err := cfg.Parse(os.Args[1:]) // This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, cfg.dsn)
|
||||
db, _ := sql.Open("mysql", dbDSN) // $ Alert[go/dsn-injection-local]
|
||||
db, _ := sql.Open("mysql", dbDSN)
|
||||
return db, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: experimental/CWE-74/DsnInjection.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: experimental/CWE-74/DsnInjectionLocal.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: experimental/CWE-807/SensitiveConditionBypass.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
experimental/CWE-807/SensitiveConditionBypass.ql
|
||||
|
||||
@@ -4,7 +4,7 @@ import "net/http"
|
||||
|
||||
func example(w http.ResponseWriter, r *http.Request) {
|
||||
test2 := "test"
|
||||
if r.Header.Get("X-Password") != test2 { // $ Alert
|
||||
if r.Header.Get("X-Password") != test2 {
|
||||
login()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ const test = "localhost"
|
||||
|
||||
// Should alert as authkey is sensitive
|
||||
func ex1(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("Origin") != test { // $ Alert
|
||||
if r.Header.Get("Origin") != test {
|
||||
authkey := "randomDatta"
|
||||
io.WriteString(w, authkey)
|
||||
}
|
||||
@@ -22,7 +22,7 @@ func ex1(w http.ResponseWriter, r *http.Request) {
|
||||
// Should alert as authkey is sensitive
|
||||
func ex2(w http.ResponseWriter, r *http.Request) {
|
||||
test2 := "test"
|
||||
if r.Header.Get("Origin") != test2 { // $ Alert
|
||||
if r.Header.Get("Origin") != test2 {
|
||||
authkey := "randomDatta2"
|
||||
io.WriteString(w, authkey)
|
||||
}
|
||||
@@ -31,7 +31,7 @@ func ex2(w http.ResponseWriter, r *http.Request) {
|
||||
// Should alert as login() is sensitive
|
||||
func ex3(w http.ResponseWriter, r *http.Request) {
|
||||
test2 := "test"
|
||||
if r.Header.Get("Origin") != test2 { // $ Alert
|
||||
if r.Header.Get("Origin") != test2 {
|
||||
login()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: experimental/CWE-840/ConditionalBypass.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
experimental/CWE-840/ConditionalBypass.ql
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
func exampleHandlerBad(w http.ResponseWriter, r *http.Request) {
|
||||
// BAD: the Origin and Host headers are user controlled
|
||||
if r.Header.Get("Origin") != "http://"+r.Host { // $ Alert
|
||||
if r.Header.Get("Origin") != "http://"+r.Host {
|
||||
//do something
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,14 @@ import (
|
||||
|
||||
// BAD: taken from https://www.gorillatoolkit.org/pkg/websocket
|
||||
func ex1(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("Origin") != "http://"+r.Host { // $ Alert
|
||||
if r.Header.Get("Origin") != "http://"+r.Host {
|
||||
//do something
|
||||
}
|
||||
}
|
||||
|
||||
// BAD: both operands are from remote sources
|
||||
func ex2(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("Origin") != "http://"+r.Header.Get("Header") { // $ Alert
|
||||
if r.Header.Get("Origin") != "http://"+r.Header.Get("Header") {
|
||||
//do something
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import "os"
|
||||
func openFiles(filenames []string) {
|
||||
for _, filename := range filenames {
|
||||
file, err := os.Open(filename)
|
||||
defer file.Close() // $ Alert[go/examples/deferinloop]
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: experimental/InconsistentCode/DeferInLoop.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
experimental/InconsistentCode/DeferInLoop.ql
|
||||
|
||||
@@ -4,6 +4,6 @@ import "gorm.io/gorm"
|
||||
|
||||
func getUserId(db *gorm.DB, name string) int64 {
|
||||
var user User
|
||||
db.Where("name = ?", name).First(&user) // $ Alert[go/examples/gorm-error-not-checked]
|
||||
db.Where("name = ?", name).First(&user)
|
||||
return user.Id
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: experimental/InconsistentCode/GORMErrorNotChecked.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
experimental/InconsistentCode/GORMErrorNotChecked.ql
|
||||
|
||||
@@ -3,24 +3,24 @@ package main
|
||||
func test() {
|
||||
var xs []int
|
||||
for _ = range xs {
|
||||
defer test() // $ Alert[go/examples/deferinloop] // not ok
|
||||
defer test() // not ok
|
||||
}
|
||||
|
||||
for _ = range xs {
|
||||
if true {
|
||||
defer test() // $ Alert[go/examples/deferinloop] // not ok
|
||||
defer test() // not ok
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
defer test() // $ Alert[go/examples/deferinloop]
|
||||
defer test()
|
||||
}
|
||||
|
||||
for true {
|
||||
defer test() // $ Alert[go/examples/deferinloop] // not ok
|
||||
defer test() // not ok
|
||||
}
|
||||
|
||||
for false {
|
||||
defer test() // $ Alert[go/examples/deferinloop] // fine but caught
|
||||
defer test() // fine but caught
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
#select
|
||||
| WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | $@. | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | Dangerous array type casting to [8]uint8 from an index expression ([8]uint8)[2] (the destination type is 2 elements longer) |
|
||||
| WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | $@. | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | Dangerous array type casting to [17]uint8 from an index expression ([8]uint8)[0] (the destination type is 9 elements longer) |
|
||||
| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | $@. | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | $@. | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | $@. | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | Dangerous array type casting to [17]string from [8]string |
|
||||
| WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | $@. | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | Dangerous type up-casting to [17]uint8 from struct type |
|
||||
| WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | $@. | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | $@. | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | $@. | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | Dangerous array type casting to [4]int64 from [1]int64 |
|
||||
| WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | $@. | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | Dangerous numeric type casting to int64 from int8 |
|
||||
| WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | $@. | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | Dangerous numeric type casting to int from int8 |
|
||||
edges
|
||||
| WrongUsageOfUnsafe.go:17:24:17:48 | type conversion | WrongUsageOfUnsafe.go:17:13:17:49 | type conversion | provenance | |
|
||||
| WrongUsageOfUnsafe.go:34:24:34:51 | type conversion | WrongUsageOfUnsafe.go:34:13:34:52 | type conversion | provenance | |
|
||||
@@ -60,3 +48,15 @@ nodes
|
||||
| WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | semmle.label | type conversion |
|
||||
| WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | semmle.label | type conversion |
|
||||
subpaths
|
||||
#select
|
||||
| WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | $@. | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | Dangerous array type casting to [8]uint8 from an index expression ([8]uint8)[2] (the destination type is 2 elements longer) |
|
||||
| WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | $@. | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | Dangerous array type casting to [17]uint8 from an index expression ([8]uint8)[0] (the destination type is 9 elements longer) |
|
||||
| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | $@. | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | $@. | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | $@. | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | Dangerous array type casting to [17]string from [8]string |
|
||||
| WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | $@. | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | Dangerous type up-casting to [17]uint8 from struct type |
|
||||
| WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | $@. | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | $@. | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
|
||||
| WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | $@. | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | Dangerous array type casting to [4]int64 from [1]int64 |
|
||||
| WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | $@. | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | Dangerous numeric type casting to int64 from int8 |
|
||||
| WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | $@. | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | Dangerous numeric type casting to int from int8 |
|
||||
|
||||
@@ -74,7 +74,7 @@ func badIndexExpr() {
|
||||
// the address of the 3rd element of the `harmless` array,
|
||||
// and continue for 8 bytes, going out of the boundaries of
|
||||
// `harmless` and crossing into the memory occupied by `secret`.
|
||||
var leaking = (*[8]byte)(unsafe.Pointer(&harmless[2])) // $ Alert // BAD
|
||||
var leaking = (*[8]byte)(unsafe.Pointer(&harmless[2])) // BAD
|
||||
|
||||
fmt.Println(string((*leaking)[:]))
|
||||
|
||||
@@ -108,7 +108,7 @@ func bad0() {
|
||||
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we get the pointer to the first byte of harmless)
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless[0])) // $ Alert // BAD
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless[0])) // BAD
|
||||
|
||||
fmt.Println(string((*leaking)[:]))
|
||||
|
||||
@@ -126,7 +126,7 @@ func bad1() {
|
||||
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless)
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD
|
||||
|
||||
fmt.Println(string((*leaking)[:]))
|
||||
|
||||
@@ -146,7 +146,7 @@ func bad2() {
|
||||
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless)
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD
|
||||
|
||||
fmt.Println(string((*leaking)[:]))
|
||||
|
||||
@@ -163,7 +163,7 @@ func bad3() {
|
||||
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless)
|
||||
var leaking = (*[8 + 9]string)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
var leaking = (*[8 + 9]string)(unsafe.Pointer(&harmless)) // BAD
|
||||
|
||||
fmt.Println(*leaking)
|
||||
fmt.Println([17]string((*leaking)))
|
||||
@@ -186,7 +186,7 @@ func bad4() {
|
||||
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless)
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD
|
||||
|
||||
fmt.Println(string((*leaking)[:]))
|
||||
|
||||
@@ -208,7 +208,7 @@ func bad5() {
|
||||
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless)
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless.Data)) // $ Alert // BAD
|
||||
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless.Data)) // BAD
|
||||
|
||||
fmt.Println(string(leaking[:]))
|
||||
|
||||
@@ -224,7 +224,7 @@ func bad6() {
|
||||
secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'}
|
||||
|
||||
// Read before secret:
|
||||
var leaking = buffer_request(unsafe.Pointer(&harmless)) // $ Source // BAD (see inside buffer_request func)
|
||||
var leaking = buffer_request(unsafe.Pointer(&harmless)) // BAD (see inside buffer_request func)
|
||||
|
||||
fmt.Println((string)(leaking[:]))
|
||||
|
||||
@@ -240,7 +240,7 @@ func buffer_request(req unsafe.Pointer) [8 + 9]byte {
|
||||
// will be read, the read will also contain pieces of
|
||||
// data from `secret`.
|
||||
var buf [8 + 9]byte
|
||||
buf = *(*[8 + 9]byte)(req) // $ Alert // BAD (from above func)
|
||||
buf = *(*[8 + 9]byte)(req) // BAD (from above func)
|
||||
return buf
|
||||
}
|
||||
func bad7() {
|
||||
@@ -253,7 +253,7 @@ func bad7() {
|
||||
// (notice we read more than the length of harmless);
|
||||
// the leaking array will not contain letters,
|
||||
// but integers representing bytes from `secret`.
|
||||
var leaking = (*[4]int64)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
var leaking = (*[4]int64)(unsafe.Pointer(&harmless)) // BAD
|
||||
|
||||
fmt.Println(*leaking)
|
||||
|
||||
@@ -271,7 +271,7 @@ func bad8() {
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless);
|
||||
// the leaking data will contain some bits from `secret`.
|
||||
var leaking = (*int64)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
var leaking = (*int64)(unsafe.Pointer(&harmless)) // BAD
|
||||
|
||||
fmt.Println(*leaking)
|
||||
|
||||
@@ -289,7 +289,7 @@ func bad9() {
|
||||
// Read before secret, overflowing into secret
|
||||
// (notice we read more than the length of harmless);
|
||||
// the leaking data will contain some bits from `secret`.
|
||||
var leaking = (*int)(unsafe.Pointer(&harmless)) // $ Alert // BAD
|
||||
var leaking = (*int)(unsafe.Pointer(&harmless)) // BAD
|
||||
|
||||
fmt.Println(*leaking)
|
||||
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: experimental/Unsafe/WrongUsageOfUnsafe.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
experimental/Unsafe/WrongUsageOfUnsafe.ql
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: Security/CWE-089/SqlInjection.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: Security/CWE-079/StoredXss.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -8,61 +8,61 @@ import (
|
||||
|
||||
// BAD: using untrusted data in SQL queries
|
||||
func testDbMethods(bdb *orm.DB, untrustedSource *http.Request) {
|
||||
untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection]
|
||||
untrusted := untrustedSource.UserAgent()
|
||||
|
||||
bdb.Exec(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
bdb.ExecContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
bdb.Prepare(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
bdb.PrepareContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
bdb.Query(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
bdb.QueryContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
bdb.QueryRow(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
bdb.QueryRowContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
bdb.Exec(untrusted) // $ querystring=untrusted
|
||||
bdb.ExecContext(nil, untrusted) // $ querystring=untrusted
|
||||
bdb.Prepare(untrusted) // $ querystring=untrusted
|
||||
bdb.PrepareContext(nil, untrusted) // $ querystring=untrusted
|
||||
bdb.Query(untrusted) // $ querystring=untrusted
|
||||
bdb.QueryContext(nil, untrusted) // $ querystring=untrusted
|
||||
bdb.QueryRow(untrusted) // $ querystring=untrusted
|
||||
bdb.QueryRowContext(nil, untrusted) // $ querystring=untrusted
|
||||
}
|
||||
|
||||
// BAD: using untrusted data to build SQL queries (QueryBuilder does not sanitize its arguments)
|
||||
func testQueryBuilderMethods(qb orm.QueryBuilder, untrustedSource *http.Request) {
|
||||
untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection]
|
||||
untrusted2 := untrustedSource.UserAgent() // $ Source[go/sql-injection]
|
||||
untrusted := untrustedSource.UserAgent()
|
||||
untrusted2 := untrustedSource.UserAgent()
|
||||
|
||||
qb.Select(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.From(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.InnerJoin(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.LeftJoin(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.RightJoin(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.On(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.Where(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.And(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.Or(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.In(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.OrderBy(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.GroupBy(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.Having(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.Update(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.Set(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.Delete(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.InsertInto(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2 Alert[go/sql-injection]
|
||||
qb.Values(untrusted) // $ querystring=untrusted Alert[go/sql-injection]
|
||||
qb.Subquery(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2 Alert[go/sql-injection]
|
||||
qb.Select(untrusted) // $ querystring=untrusted
|
||||
qb.From(untrusted) // $ querystring=untrusted
|
||||
qb.InnerJoin(untrusted) // $ querystring=untrusted
|
||||
qb.LeftJoin(untrusted) // $ querystring=untrusted
|
||||
qb.RightJoin(untrusted) // $ querystring=untrusted
|
||||
qb.On(untrusted) // $ querystring=untrusted
|
||||
qb.Where(untrusted) // $ querystring=untrusted
|
||||
qb.And(untrusted) // $ querystring=untrusted
|
||||
qb.Or(untrusted) // $ querystring=untrusted
|
||||
qb.In(untrusted) // $ querystring=untrusted
|
||||
qb.OrderBy(untrusted) // $ querystring=untrusted
|
||||
qb.GroupBy(untrusted) // $ querystring=untrusted
|
||||
qb.Having(untrusted) // $ querystring=untrusted
|
||||
qb.Update(untrusted) // $ querystring=untrusted
|
||||
qb.Set(untrusted) // $ querystring=untrusted
|
||||
qb.Delete(untrusted) // $ querystring=untrusted
|
||||
qb.InsertInto(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2
|
||||
qb.Values(untrusted) // $ querystring=untrusted
|
||||
qb.Subquery(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2
|
||||
}
|
||||
|
||||
func testOrmerRaw(ormer orm.Ormer, untrustedSource *http.Request) {
|
||||
untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection]
|
||||
untrusted := untrustedSource.UserAgent()
|
||||
untrusted2 := untrustedSource.UserAgent()
|
||||
ormer.Raw(untrusted, untrusted2) // $ querystring=untrusted Alert[go/sql-injection] // BAD: using an untrusted string as a query
|
||||
ormer.Raw(untrusted, untrusted2) // $ querystring=untrusted // BAD: using an untrusted string as a query
|
||||
ormer.Raw("FROM ? SELECT ?", untrusted, untrusted2) // $ querystring="FROM ? SELECT ?" // GOOD: untrusted string used in argument context
|
||||
}
|
||||
|
||||
func testFilterRaw(querySeter orm.QuerySeter, untrustedSource *http.Request) {
|
||||
untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection]
|
||||
querySeter.FilterRaw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name
|
||||
querySeter.FilterRaw("safe", untrusted) // $ querystring=untrusted Alert[go/sql-injection] // BAD: untrusted used as a SQL fragment
|
||||
untrusted := untrustedSource.UserAgent()
|
||||
querySeter.FilterRaw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name
|
||||
querySeter.FilterRaw("safe", untrusted) // $ querystring=untrusted // BAD: untrusted used as a SQL fragment
|
||||
}
|
||||
|
||||
func testConditionRaw(cond orm.Condition, untrustedSource *http.Request) {
|
||||
untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection]
|
||||
cond.Raw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name
|
||||
cond.Raw("safe", untrusted) // $ querystring=untrusted Alert[go/sql-injection] // BAD: untrusted used as a SQL fragment
|
||||
untrusted := untrustedSource.UserAgent()
|
||||
cond.Raw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name
|
||||
cond.Raw("safe", untrusted) // $ querystring=untrusted // BAD: untrusted used as a SQL fragment
|
||||
}
|
||||
|
||||
type SubStruct struct {
|
||||
@@ -77,90 +77,90 @@ type MyStruct struct {
|
||||
// BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response
|
||||
func testOrmerReads(ormer orm.Ormer, sink http.ResponseWriter) {
|
||||
obj := MyStruct{}
|
||||
ormer.Read(&obj) // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(obj.field)) // $ Alert[go/stored-xss]
|
||||
sink.Write([]byte(obj.substructs[0].field)) // $ Alert[go/stored-xss]
|
||||
ormer.Read(&obj)
|
||||
sink.Write([]byte(obj.field))
|
||||
sink.Write([]byte(obj.substructs[0].field))
|
||||
|
||||
obj2 := MyStruct{}
|
||||
ormer.ReadForUpdate(&obj2) // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(obj2.field)) // $ Alert[go/stored-xss]
|
||||
ormer.ReadForUpdate(&obj2)
|
||||
sink.Write([]byte(obj2.field))
|
||||
|
||||
obj3 := MyStruct{}
|
||||
ormer.ReadOrCreate(&obj3, "arg") // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(obj3.field)) // $ Alert[go/stored-xss]
|
||||
ormer.ReadOrCreate(&obj3, "arg")
|
||||
sink.Write([]byte(obj3.field))
|
||||
}
|
||||
|
||||
// BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response
|
||||
func testFieldReads(textField *orm.TextField, jsonField *orm.JSONField, jsonbField *orm.JsonbField, sink http.ResponseWriter) {
|
||||
sink.Write([]byte(textField.Value())) // $ Alert[go/stored-xss]
|
||||
sink.Write([]byte(textField.RawValue().(string))) // $ Alert[go/stored-xss]
|
||||
sink.Write([]byte(textField.String())) // $ Alert[go/stored-xss]
|
||||
sink.Write([]byte(jsonField.Value())) // $ Alert[go/stored-xss]
|
||||
sink.Write([]byte(jsonField.RawValue().(string))) // $ Alert[go/stored-xss]
|
||||
sink.Write([]byte(jsonField.String())) // $ Alert[go/stored-xss]
|
||||
sink.Write([]byte(jsonbField.Value())) // $ Alert[go/stored-xss]
|
||||
sink.Write([]byte(jsonbField.RawValue().(string))) // $ Alert[go/stored-xss]
|
||||
sink.Write([]byte(jsonbField.String())) // $ Alert[go/stored-xss]
|
||||
sink.Write([]byte(textField.Value()))
|
||||
sink.Write([]byte(textField.RawValue().(string)))
|
||||
sink.Write([]byte(textField.String()))
|
||||
sink.Write([]byte(jsonField.Value()))
|
||||
sink.Write([]byte(jsonField.RawValue().(string)))
|
||||
sink.Write([]byte(jsonField.String()))
|
||||
sink.Write([]byte(jsonbField.Value()))
|
||||
sink.Write([]byte(jsonbField.RawValue().(string)))
|
||||
sink.Write([]byte(jsonbField.String()))
|
||||
}
|
||||
|
||||
// BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response
|
||||
func testQuerySeterReads(qs orm.QuerySeter, sink http.ResponseWriter) {
|
||||
var objs []*MyStruct
|
||||
qs.All(&objs) // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(objs[0].field)) // $ Alert[go/stored-xss]
|
||||
qs.All(&objs)
|
||||
sink.Write([]byte(objs[0].field))
|
||||
|
||||
var obj MyStruct
|
||||
qs.One(&obj) // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(obj.field)) // $ Alert[go/stored-xss]
|
||||
qs.One(&obj)
|
||||
sink.Write([]byte(obj.field))
|
||||
|
||||
var allMaps []orm.Params
|
||||
qs.Values(&allMaps) // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(allMaps[0]["field"].(string))) // $ Alert[go/stored-xss]
|
||||
qs.Values(&allMaps)
|
||||
sink.Write([]byte(allMaps[0]["field"].(string)))
|
||||
|
||||
var allLists []orm.ParamsList
|
||||
qs.ValuesList(&allLists) // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(allLists[0][0].(string))) // $ Alert[go/stored-xss]
|
||||
qs.ValuesList(&allLists)
|
||||
sink.Write([]byte(allLists[0][0].(string)))
|
||||
|
||||
var oneList orm.ParamsList
|
||||
qs.ValuesFlat(&oneList, "colname") // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(oneList[0].(string))) // $ Alert[go/stored-xss]
|
||||
qs.ValuesFlat(&oneList, "colname")
|
||||
sink.Write([]byte(oneList[0].(string)))
|
||||
|
||||
var oneRowMap orm.Params
|
||||
qs.RowsToMap(&oneRowMap, "key", "value") // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(oneRowMap["field"].(string))) // $ Alert[go/stored-xss]
|
||||
qs.RowsToMap(&oneRowMap, "key", "value")
|
||||
sink.Write([]byte(oneRowMap["field"].(string)))
|
||||
|
||||
var oneRowStruct MyStruct
|
||||
qs.RowsToStruct(&oneRowStruct, "key", "value") // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(oneRowStruct.field)) // $ Alert[go/stored-xss]
|
||||
qs.RowsToStruct(&oneRowStruct, "key", "value")
|
||||
sink.Write([]byte(oneRowStruct.field))
|
||||
}
|
||||
|
||||
// BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response
|
||||
func testRawSeterReads(rs orm.RawSeter, sink http.ResponseWriter) {
|
||||
var allMaps []orm.Params
|
||||
rs.Values(&allMaps) // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(allMaps[0]["field"].(string))) // $ Alert[go/stored-xss]
|
||||
rs.Values(&allMaps)
|
||||
sink.Write([]byte(allMaps[0]["field"].(string)))
|
||||
|
||||
var allLists []orm.ParamsList
|
||||
rs.ValuesList(&allLists) // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(allLists[0][0].(string))) // $ Alert[go/stored-xss]
|
||||
rs.ValuesList(&allLists)
|
||||
sink.Write([]byte(allLists[0][0].(string)))
|
||||
|
||||
var oneList orm.ParamsList
|
||||
rs.ValuesFlat(&oneList, "colname") // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(oneList[0].(string))) // $ Alert[go/stored-xss]
|
||||
rs.ValuesFlat(&oneList, "colname")
|
||||
sink.Write([]byte(oneList[0].(string)))
|
||||
|
||||
var oneRowMap orm.Params
|
||||
rs.RowsToMap(&oneRowMap, "key", "value") // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(oneRowMap["field"].(string))) // $ Alert[go/stored-xss]
|
||||
rs.RowsToMap(&oneRowMap, "key", "value")
|
||||
sink.Write([]byte(oneRowMap["field"].(string)))
|
||||
|
||||
var oneRowStruct MyStruct
|
||||
rs.RowsToStruct(&oneRowStruct, "key", "value") // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(oneRowStruct.field)) // $ Alert[go/stored-xss]
|
||||
rs.RowsToStruct(&oneRowStruct, "key", "value")
|
||||
sink.Write([]byte(oneRowStruct.field))
|
||||
|
||||
var strField string
|
||||
rs.QueryRow(&strField) // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(strField)) // $ Alert[go/stored-xss]
|
||||
rs.QueryRow(&strField)
|
||||
sink.Write([]byte(strField))
|
||||
|
||||
var strFields []string
|
||||
rs.QueryRows(&strFields) // $ Source[go/stored-xss]
|
||||
sink.Write([]byte(strFields[0])) // $ Alert[go/stored-xss]
|
||||
rs.QueryRows(&strFields)
|
||||
sink.Write([]byte(strFields[0]))
|
||||
}
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: Security/CWE-079/ReflectedXss.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -10,7 +10,7 @@ var hidden string
|
||||
|
||||
func hideUserData(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
hidden = r.URL.Path // $ Source
|
||||
hidden = r.URL.Path
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
@@ -18,10 +18,10 @@ func hideUserData(next http.Handler) http.Handler {
|
||||
func main() {
|
||||
r := chi.NewRouter()
|
||||
r.With(hideUserData).Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte(hidden)) // $ Alert
|
||||
w.Write([]byte(chi.URLParam(r, "someParam"))) // $ Alert
|
||||
w.Write([]byte(chi.URLParamFromCtx(r.Context(), "someKey"))) // $ Alert
|
||||
w.Write([]byte(chi.RouteContext(r.Context()).URLParam("someOtherKey"))) // $ Alert
|
||||
w.Write([]byte(hidden))
|
||||
w.Write([]byte(chi.URLParam(r, "someParam")))
|
||||
w.Write([]byte(chi.URLParamFromCtx(r.Context(), "someKey")))
|
||||
w.Write([]byte(chi.RouteContext(r.Context()).URLParam("someOtherKey")))
|
||||
})
|
||||
http.ListenAndServe(":3000", r)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: Security/CWE-601/OpenUrlRedirect.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: Security/CWE-079/ReflectedXss.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: Security/CWE-022/TaintedPath.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -12,81 +12,81 @@ import (
|
||||
// All are XSS vulnerabilities, except as specifically noted.
|
||||
|
||||
func testParam(ctx echo.Context) error {
|
||||
param := ctx.Param("someParam") // $ Source[go/reflected-xss]
|
||||
ctx.HTML(200, param) // $ Alert[go/reflected-xss]
|
||||
param := ctx.Param("someParam")
|
||||
ctx.HTML(200, param)
|
||||
return nil
|
||||
}
|
||||
|
||||
func testParamValues(ctx echo.Context) error {
|
||||
param := ctx.ParamValues()[0] // $ Source[go/reflected-xss]
|
||||
ctx.HTML(200, param) // $ Alert[go/reflected-xss]
|
||||
param := ctx.ParamValues()[0]
|
||||
ctx.HTML(200, param)
|
||||
return nil
|
||||
}
|
||||
|
||||
func testQueryParam(ctx echo.Context) error {
|
||||
param := ctx.QueryParam("someParam") // $ Source[go/reflected-xss]
|
||||
ctx.HTML(200, param) // $ Alert[go/reflected-xss]
|
||||
param := ctx.QueryParam("someParam")
|
||||
ctx.HTML(200, param)
|
||||
return nil
|
||||
}
|
||||
|
||||
func testQueryParams(ctx echo.Context) error {
|
||||
param := ctx.QueryParams()["someParam"][0] // $ Source[go/reflected-xss]
|
||||
ctx.HTML(200, param) // $ Alert[go/reflected-xss]
|
||||
param := ctx.QueryParams()["someParam"][0]
|
||||
ctx.HTML(200, param)
|
||||
return nil
|
||||
}
|
||||
|
||||
func testQueryString(ctx echo.Context) error {
|
||||
qstr := ctx.QueryString() // $ Source[go/reflected-xss]
|
||||
ctx.HTML(200, qstr) // $ Alert[go/reflected-xss]
|
||||
qstr := ctx.QueryString()
|
||||
ctx.HTML(200, qstr)
|
||||
return nil
|
||||
}
|
||||
|
||||
func testFormValue(ctx echo.Context) error {
|
||||
val := ctx.FormValue("someField") // $ Source[go/reflected-xss]
|
||||
ctx.HTML(200, val) // $ Alert[go/reflected-xss]
|
||||
val := ctx.FormValue("someField")
|
||||
ctx.HTML(200, val)
|
||||
return nil
|
||||
}
|
||||
|
||||
func testFormParams(ctx echo.Context) error {
|
||||
params, _ := ctx.FormParams() // $ Source[go/reflected-xss]
|
||||
ctx.HTML(200, params["someField"][0]) // $ Alert[go/reflected-xss]
|
||||
params, _ := ctx.FormParams()
|
||||
ctx.HTML(200, params["someField"][0])
|
||||
return nil
|
||||
}
|
||||
|
||||
func testFormFile(ctx echo.Context) error {
|
||||
fileHeader, _ := ctx.FormFile("someFilename") // $ Source[go/reflected-xss]
|
||||
fileHeader, _ := ctx.FormFile("someFilename")
|
||||
file, _ := fileHeader.Open()
|
||||
buffer := make([]byte, 100)
|
||||
file.Read(buffer)
|
||||
ctx.HTMLBlob(200, buffer) // $ Alert[go/reflected-xss]
|
||||
ctx.HTMLBlob(200, buffer)
|
||||
return nil
|
||||
}
|
||||
|
||||
func testMultipartFormValue(ctx echo.Context) error {
|
||||
form, _ := ctx.MultipartForm() // $ Source[go/reflected-xss]
|
||||
ctx.HTML(200, form.Value["someField"][0]) // $ Alert[go/reflected-xss]
|
||||
form, _ := ctx.MultipartForm()
|
||||
ctx.HTML(200, form.Value["someField"][0])
|
||||
return nil
|
||||
}
|
||||
|
||||
func testMultipartFormFile(ctx echo.Context) error {
|
||||
form, _ := ctx.MultipartForm() // $ Source[go/reflected-xss]
|
||||
form, _ := ctx.MultipartForm()
|
||||
fileHeader := form.File["someFilename"][0]
|
||||
file, _ := fileHeader.Open()
|
||||
buffer := make([]byte, 100)
|
||||
file.Read(buffer)
|
||||
ctx.HTMLBlob(200, buffer) // $ Alert[go/reflected-xss]
|
||||
ctx.HTMLBlob(200, buffer)
|
||||
return nil
|
||||
}
|
||||
|
||||
func testCookie(ctx echo.Context) error {
|
||||
val, _ := ctx.Cookie("someKey") // $ Source[go/reflected-xss]
|
||||
ctx.HTML(200, val.Value) // $ Alert[go/reflected-xss]
|
||||
val, _ := ctx.Cookie("someKey")
|
||||
ctx.HTML(200, val.Value)
|
||||
return nil
|
||||
}
|
||||
|
||||
func testCookies(ctx echo.Context) error {
|
||||
cookies := ctx.Cookies() // $ Source[go/reflected-xss]
|
||||
ctx.HTML(200, cookies[0].Value) // $ Alert[go/reflected-xss]
|
||||
cookies := ctx.Cookies()
|
||||
ctx.HTML(200, cookies[0].Value)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -96,8 +96,8 @@ type myStruct struct {
|
||||
|
||||
func testBind(ctx echo.Context) error {
|
||||
data := myStruct{}
|
||||
ctx.Bind(&data) // $ Source[go/reflected-xss]
|
||||
ctx.HTML(200, data.s) // $ Alert[go/reflected-xss]
|
||||
ctx.Bind(&data)
|
||||
ctx.HTML(200, data.s)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -110,8 +110,8 @@ func testGetSetEmpty(ctx echo.Context) error {
|
||||
}
|
||||
|
||||
func testGetSet(ctx echo.Context) error {
|
||||
ctx.Set("someKey", ctx.Param("someParam")) // $ Source[go/reflected-xss]
|
||||
ctx.HTML(200, ctx.Get("someKey").(string)) // $ Alert[go/reflected-xss] // BAD, the context is tainted
|
||||
ctx.Set("someKey", ctx.Param("someParam"))
|
||||
ctx.HTML(200, ctx.Get("someKey").(string)) // BAD, the context is tainted
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -121,20 +121,20 @@ func testGetSet(ctx echo.Context) error {
|
||||
// All are XSS vulnerabilities, except as specifically noted.
|
||||
|
||||
func testHTML(ctx echo.Context) error {
|
||||
param := ctx.Param("someParam") // $ Source[go/reflected-xss]
|
||||
ctx.HTML(200, param) // $ Alert[go/reflected-xss]
|
||||
param := ctx.Param("someParam")
|
||||
ctx.HTML(200, param)
|
||||
return nil
|
||||
}
|
||||
|
||||
func testHTMLBlob(ctx echo.Context) error {
|
||||
param := ctx.Param("someParam") // $ Source[go/reflected-xss]
|
||||
ctx.HTMLBlob(200, []byte(param)) // $ Alert[go/reflected-xss]
|
||||
param := ctx.Param("someParam")
|
||||
ctx.HTMLBlob(200, []byte(param))
|
||||
return nil
|
||||
}
|
||||
|
||||
func testBlob(ctx echo.Context) error {
|
||||
param := ctx.Param("someParam") // $ Source[go/reflected-xss]
|
||||
ctx.Blob(200, "text/html", []byte(param)) // $ Alert[go/reflected-xss] // BAD, the content-type is HTML
|
||||
param := ctx.Param("someParam")
|
||||
ctx.Blob(200, "text/html", []byte(param)) // BAD, the content-type is HTML
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -145,9 +145,9 @@ func testBlobSafe(ctx echo.Context) error {
|
||||
}
|
||||
|
||||
func testStream(ctx echo.Context) error {
|
||||
param := ctx.Param("someParam") // $ Source[go/reflected-xss]
|
||||
param := ctx.Param("someParam")
|
||||
reader := strings.NewReader(param)
|
||||
ctx.Stream(200, "text/html", reader) // $ Alert[go/reflected-xss] // BAD, the content-type is HTML
|
||||
ctx.Stream(200, "text/html", reader) // BAD, the content-type is HTML
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -161,28 +161,28 @@ func testStreamSafe(ctx echo.Context) error {
|
||||
// Section: testing output methods defined on Response (XSS vulnerability)
|
||||
|
||||
func testResponseWrite(ctx echo.Context) error {
|
||||
param := ctx.Param("someParam") // $ Source[go/reflected-xss]
|
||||
ctx.Response().Write([]byte(param)) // $ Alert[go/reflected-xss]
|
||||
param := ctx.Param("someParam")
|
||||
ctx.Response().Write([]byte(param))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Section: test detecting an open redirect using the Context.Redirect function:
|
||||
|
||||
func testRedirect(ctx echo.Context) error {
|
||||
param := ctx.Param("someParam") // $ Source[go/unvalidated-url-redirection]
|
||||
ctx.Redirect(301, param) // $ Alert[go/unvalidated-url-redirection]
|
||||
param := ctx.Param("someParam")
|
||||
ctx.Redirect(301, param)
|
||||
return nil
|
||||
}
|
||||
|
||||
func testLocalRedirects(ctx echo.Context) error {
|
||||
param := ctx.Param("someParam") // $ Source[go/unvalidated-url-redirection]
|
||||
param := ctx.Param("someParam")
|
||||
param2 := param
|
||||
param3 := param
|
||||
// Gratuitous copy because sanitization of uses propagates to subsequent uses
|
||||
// GOOD: local redirects are unproblematic
|
||||
ctx.Redirect(301, "/local"+param)
|
||||
// BAD: this could be a non-local redirect
|
||||
ctx.Redirect(301, "/"+param2) // $ Alert[go/unvalidated-url-redirection]
|
||||
ctx.Redirect(301, "/"+param2)
|
||||
// GOOD: localhost redirects are unproblematic
|
||||
ctx.Redirect(301, "//localhost/"+param3)
|
||||
return nil
|
||||
@@ -221,12 +221,12 @@ func testNonExploitableFields(ctx echo.Context) error {
|
||||
func fsOpsTest() {
|
||||
e := echo.New()
|
||||
e.GET("/", func(c echo.Context) error {
|
||||
filepath := c.QueryParam("filePath") // $ Source[go/path-injection]
|
||||
return c.File(filepath) // $ FileSystemAccess=filepath Alert[go/path-injection]
|
||||
filepath := c.QueryParam("filePath")
|
||||
return c.File(filepath) // $ FileSystemAccess=filepath
|
||||
})
|
||||
e.GET("/attachment", func(c echo.Context) error {
|
||||
filepath := c.QueryParam("filePath") // $ Source[go/path-injection]
|
||||
return c.Attachment(filepath, "file name in response") // $ FileSystemAccess=filepath Alert[go/path-injection]
|
||||
filepath := c.QueryParam("filePath")
|
||||
return c.Attachment(filepath, "file name in response") // $ FileSystemAccess=filepath
|
||||
})
|
||||
_ = e.Start(":1323")
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#select
|
||||
| main.go:21:28:21:31 | name | main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | This log entry depends on a $@. | main.go:18:46:18:48 | definition of req | user-provided value |
|
||||
edges
|
||||
| main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | provenance | |
|
||||
nodes
|
||||
| main.go:18:46:18:48 | definition of req | semmle.label | definition of req |
|
||||
| main.go:21:28:21:31 | name | semmle.label | name |
|
||||
subpaths
|
||||
#select
|
||||
| main.go:21:28:21:31 | name | main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | This log entry depends on a $@. | main.go:18:46:18:48 | definition of req | user-provided value |
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: Security/CWE-117/LogInjection.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
Security/CWE-117/LogInjection.ql
|
||||
|
||||
@@ -15,10 +15,10 @@ import (
|
||||
|
||||
type Greeter struct{}
|
||||
|
||||
func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error { // $ serverRequest="definition of req" Source
|
||||
func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error { // $ serverRequest="definition of req"
|
||||
// var access
|
||||
name := req.Name
|
||||
fmt.Println("Name :: %s", name) // $ Alert
|
||||
fmt.Println("Name :: %s", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
reverseRead
|
||||
| EndToEnd.go:31:35:31:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:31:35:31:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:37:18:37:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:37:18:37:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:45:18:45:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:45:18:45:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:52:20:52:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:52:20:52:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:59:18:59:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:59:18:59:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:65:26:65:26 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:65:26:65:33 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:70:22:70:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:70:22:70:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:75:22:75:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:75:22:75:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:80:35:80:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:80:35:80:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:85:22:85:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:85:22:85:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:90:21:90:21 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:90:21:90:28 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:95:20:95:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:95:20:95:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:30:35:30:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:30:35:30:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:36:18:36:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:36:18:36:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:44:18:44:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:44:18:44:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:51:20:51:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:51:20:51:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:58:18:58:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:58:18:58:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:64:26:64:26 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:64:26:64:33 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:69:22:69:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:69:22:69:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:74:22:74:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:74:22:74:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:79:35:79:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:79:35:79:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:84:22:84:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:84:22:84:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:89:21:89:21 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:89:21:89:28 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:94:20:94:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| EndToEnd.go:94:20:94:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| Revel.go:26:7:26:7 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| Revel.go:27:7:27:7 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
|
||||
| Revel.go:27:7:27:14 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
|
||||
@@ -3,11 +3,10 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
staticControllers "github.com/revel/modules/static/app/controllers"
|
||||
"github.com/revel/revel"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Use typical inheritence pattern, per github.com/revel/examples/booking:
|
||||
@@ -34,8 +33,8 @@ func (c MyRoute) Handler1() revel.Result {
|
||||
func (c MyRoute) Handler2() revel.Result {
|
||||
// BAD: the RenderBinary function copies an `io.Reader` to the user's browser.
|
||||
buf := &bytes.Buffer{}
|
||||
buf.WriteString(c.Params.Form.Get("someField")) // $ Source[go/reflected-xss]
|
||||
return c.RenderBinary(buf, "index.html", revel.Inline, time.Now()) // $ responsebody='buf' Alert[go/reflected-xss]
|
||||
buf.WriteString(c.Params.Form.Get("someField"))
|
||||
return c.RenderBinary(buf, "index.html", revel.Inline, time.Now()) // $ responsebody='buf'
|
||||
}
|
||||
|
||||
func (c MyRoute) Handler3() revel.Result {
|
||||
@@ -56,18 +55,18 @@ func (c MyRoute) Handler4() revel.Result {
|
||||
func (c MyRoute) Handler5() revel.Result {
|
||||
// BAD: returning an arbitrary file (but this is detected at the os.Open call, not
|
||||
// due to modelling Revel)
|
||||
f, _ := os.Open(c.Params.Form.Get("someField")) // $ Alert[go/path-injection]
|
||||
f, _ := os.Open(c.Params.Form.Get("someField"))
|
||||
return c.RenderFile(f, revel.Inline)
|
||||
}
|
||||
|
||||
func (c MyRoute) Handler6() revel.Result {
|
||||
// BAD: returning an arbitrary file (detected as a user-controlled file-op, not XSS)
|
||||
return c.RenderFileName(c.Params.Form.Get("someField"), revel.Inline) // $ Alert[go/path-injection]
|
||||
return c.RenderFileName(c.Params.Form.Get("someField"), revel.Inline)
|
||||
}
|
||||
|
||||
func (c MyRoute) Handler7() revel.Result {
|
||||
// BAD: straightforward XSS
|
||||
return c.RenderHTML(c.Params.Form.Get("someField")) // $ responsebody='call to Get' Alert[go/reflected-xss]
|
||||
return c.RenderHTML(c.Params.Form.Get("someField")) // $ responsebody='call to Get'
|
||||
}
|
||||
|
||||
func (c MyRoute) Handler8() revel.Result {
|
||||
@@ -92,5 +91,5 @@ func (c MyRoute) Handler11() revel.Result {
|
||||
|
||||
func (c MyRoute) Handler12() revel.Result {
|
||||
// BAD: open redirect
|
||||
return c.Redirect(c.Params.Form.Get("someField")) // $ Alert[go/unvalidated-url-redirection]
|
||||
return c.Redirect(c.Params.Form.Get("someField"))
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#select
|
||||
| EndToEnd.go:95:20:95:49 | call to Get | EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:49 | call to Get | This path to an untrusted URL redirection depends on a $@. | EndToEnd.go:95:20:95:27 | selection of Params | user-provided value |
|
||||
| EndToEnd.go:94:20:94:49 | call to Get | EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:49 | call to Get | This path to an untrusted URL redirection depends on a $@. | EndToEnd.go:94:20:94:27 | selection of Params | user-provided value |
|
||||
edges
|
||||
| EndToEnd.go:95:20:95:27 | implicit dereference | EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | provenance | Config |
|
||||
| EndToEnd.go:95:20:95:27 | implicit dereference | EndToEnd.go:95:20:95:32 | selection of Form | provenance | Config |
|
||||
| EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:27 | implicit dereference | provenance | Src:MaD:2 Config |
|
||||
| EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:32 | selection of Form | provenance | Src:MaD:2 Config |
|
||||
| EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | EndToEnd.go:95:20:95:27 | implicit dereference | provenance | Config |
|
||||
| EndToEnd.go:95:20:95:32 | selection of Form | EndToEnd.go:95:20:95:49 | call to Get | provenance | Config Sink:MaD:1 |
|
||||
| EndToEnd.go:94:20:94:27 | implicit dereference | EndToEnd.go:94:20:94:27 | selection of Params [postupdate] | provenance | Config |
|
||||
| EndToEnd.go:94:20:94:27 | implicit dereference | EndToEnd.go:94:20:94:32 | selection of Form | provenance | Config |
|
||||
| EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:27 | implicit dereference | provenance | Src:MaD:2 Config |
|
||||
| EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:32 | selection of Form | provenance | Src:MaD:2 Config |
|
||||
| EndToEnd.go:94:20:94:27 | selection of Params [postupdate] | EndToEnd.go:94:20:94:27 | implicit dereference | provenance | Config |
|
||||
| EndToEnd.go:94:20:94:32 | selection of Form | EndToEnd.go:94:20:94:49 | call to Get | provenance | Config Sink:MaD:1 |
|
||||
models
|
||||
| 1 | Sink: group:revel; Controller; true; Redirect; ; ; Argument[0]; url-redirection; manual |
|
||||
| 2 | Source: group:revel; Controller; true; Params; ; ; ; remote; manual |
|
||||
nodes
|
||||
| EndToEnd.go:95:20:95:27 | implicit dereference | semmle.label | implicit dereference |
|
||||
| EndToEnd.go:95:20:95:27 | selection of Params | semmle.label | selection of Params |
|
||||
| EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | semmle.label | selection of Params [postupdate] |
|
||||
| EndToEnd.go:95:20:95:32 | selection of Form | semmle.label | selection of Form |
|
||||
| EndToEnd.go:95:20:95:49 | call to Get | semmle.label | call to Get |
|
||||
| EndToEnd.go:94:20:94:27 | implicit dereference | semmle.label | implicit dereference |
|
||||
| EndToEnd.go:94:20:94:27 | selection of Params | semmle.label | selection of Params |
|
||||
| EndToEnd.go:94:20:94:27 | selection of Params [postupdate] | semmle.label | selection of Params [postupdate] |
|
||||
| EndToEnd.go:94:20:94:32 | selection of Form | semmle.label | selection of Form |
|
||||
| EndToEnd.go:94:20:94:49 | call to Get | semmle.label | call to Get |
|
||||
subpaths
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: Security/CWE-601/OpenUrlRedirect.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#select
|
||||
| EndToEnd.go:38:24:38:26 | buf | EndToEnd.go:37:18:37:25 | selection of Params | EndToEnd.go:38:24:38:26 | buf | Cross-site scripting vulnerability due to $@. | EndToEnd.go:37:18:37:25 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | |
|
||||
| EndToEnd.go:70:22:70:51 | call to Get | EndToEnd.go:70:22:70:29 | selection of Params | EndToEnd.go:70:22:70:51 | call to Get | Cross-site scripting vulnerability due to $@. | EndToEnd.go:70:22:70:29 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | |
|
||||
| EndToEnd.go:37:24:37:26 | buf | EndToEnd.go:36:18:36:25 | selection of Params | EndToEnd.go:37:24:37:26 | buf | Cross-site scripting vulnerability due to $@. | EndToEnd.go:36:18:36:25 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | |
|
||||
| EndToEnd.go:69:22:69:51 | call to Get | EndToEnd.go:69:22:69:29 | selection of Params | EndToEnd.go:69:22:69:51 | call to Get | Cross-site scripting vulnerability due to $@. | EndToEnd.go:69:22:69:29 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | |
|
||||
| Revel.go:70:22:70:35 | selection of Query | Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | Cross-site scripting vulnerability due to $@. The value is $@. | Revel.go:70:22:70:29 | selection of Params | user-provided value | views/myAppController/rawRead.html:1:1:2:9 | {{raw .Foo}}\n{{.Bar}}\n | instantiated as a raw template |
|
||||
| examples/booking/app/init.go:36:44:36:53 | selection of Path | examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:36:44:36:48 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | |
|
||||
| examples/booking/app/init.go:40:49:40:58 | selection of Path | examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:40:49:40:53 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | |
|
||||
edges
|
||||
| EndToEnd.go:37:2:37:4 | buf [postupdate] | EndToEnd.go:38:24:38:26 | buf | provenance | |
|
||||
| EndToEnd.go:37:18:37:25 | selection of Params | EndToEnd.go:37:18:37:30 | selection of Form | provenance | Src:MaD:1 |
|
||||
| EndToEnd.go:37:18:37:30 | selection of Form | EndToEnd.go:37:18:37:47 | call to Get | provenance | MaD:4 |
|
||||
| EndToEnd.go:37:18:37:47 | call to Get | EndToEnd.go:37:2:37:4 | buf [postupdate] | provenance | MaD:3 |
|
||||
| EndToEnd.go:70:22:70:29 | selection of Params | EndToEnd.go:70:22:70:34 | selection of Form | provenance | Src:MaD:1 |
|
||||
| EndToEnd.go:70:22:70:34 | selection of Form | EndToEnd.go:70:22:70:51 | call to Get | provenance | MaD:4 |
|
||||
| EndToEnd.go:36:2:36:4 | buf [postupdate] | EndToEnd.go:37:24:37:26 | buf | provenance | |
|
||||
| EndToEnd.go:36:18:36:25 | selection of Params | EndToEnd.go:36:18:36:30 | selection of Form | provenance | Src:MaD:1 |
|
||||
| EndToEnd.go:36:18:36:30 | selection of Form | EndToEnd.go:36:18:36:47 | call to Get | provenance | MaD:4 |
|
||||
| EndToEnd.go:36:18:36:47 | call to Get | EndToEnd.go:36:2:36:4 | buf [postupdate] | provenance | MaD:3 |
|
||||
| EndToEnd.go:69:22:69:29 | selection of Params | EndToEnd.go:69:22:69:34 | selection of Form | provenance | Src:MaD:1 |
|
||||
| EndToEnd.go:69:22:69:34 | selection of Form | EndToEnd.go:69:22:69:51 | call to Get | provenance | MaD:4 |
|
||||
| Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | provenance | Src:MaD:1 |
|
||||
| examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | provenance | Src:MaD:2 |
|
||||
| examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | provenance | Src:MaD:2 |
|
||||
@@ -20,14 +20,14 @@ models
|
||||
| 3 | Summary: io; StringWriter; true; WriteString; ; ; Argument[0]; Argument[receiver]; taint; manual |
|
||||
| 4 | Summary: net/url; Values; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual |
|
||||
nodes
|
||||
| EndToEnd.go:37:2:37:4 | buf [postupdate] | semmle.label | buf [postupdate] |
|
||||
| EndToEnd.go:37:18:37:25 | selection of Params | semmle.label | selection of Params |
|
||||
| EndToEnd.go:37:18:37:30 | selection of Form | semmle.label | selection of Form |
|
||||
| EndToEnd.go:37:18:37:47 | call to Get | semmle.label | call to Get |
|
||||
| EndToEnd.go:38:24:38:26 | buf | semmle.label | buf |
|
||||
| EndToEnd.go:70:22:70:29 | selection of Params | semmle.label | selection of Params |
|
||||
| EndToEnd.go:70:22:70:34 | selection of Form | semmle.label | selection of Form |
|
||||
| EndToEnd.go:70:22:70:51 | call to Get | semmle.label | call to Get |
|
||||
| EndToEnd.go:36:2:36:4 | buf [postupdate] | semmle.label | buf [postupdate] |
|
||||
| EndToEnd.go:36:18:36:25 | selection of Params | semmle.label | selection of Params |
|
||||
| EndToEnd.go:36:18:36:30 | selection of Form | semmle.label | selection of Form |
|
||||
| EndToEnd.go:36:18:36:47 | call to Get | semmle.label | call to Get |
|
||||
| EndToEnd.go:37:24:37:26 | buf | semmle.label | buf |
|
||||
| EndToEnd.go:69:22:69:29 | selection of Params | semmle.label | selection of Params |
|
||||
| EndToEnd.go:69:22:69:34 | selection of Form | semmle.label | selection of Form |
|
||||
| EndToEnd.go:69:22:69:51 | call to Get | semmle.label | call to Get |
|
||||
| Revel.go:70:22:70:29 | selection of Params | semmle.label | selection of Params |
|
||||
| Revel.go:70:22:70:35 | selection of Query | semmle.label | selection of Query |
|
||||
| examples/booking/app/init.go:36:44:36:48 | selection of URL | semmle.label | selection of URL |
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: Security/CWE-079/ReflectedXss.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -67,7 +67,7 @@ func (c myAppController) accessingParamsJSONIsUnsafe() {
|
||||
func (c myAppController) rawRead() { // $ responsebody='argument corresponding to c'
|
||||
c.ViewArgs["Foo"] = "<p>raw HTML</p>" // $ responsebody='"<p>raw HTML</p>"'
|
||||
c.ViewArgs["Bar"] = "<p>not raw HTML</p>"
|
||||
c.ViewArgs["Foo"] = c.Params.Query // $ responsebody='selection of Query' Alert[go/reflected-xss]
|
||||
c.ViewArgs["Foo"] = c.Params.Query // $ responsebody='selection of Query'
|
||||
c.Render()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
#select
|
||||
| EndToEnd.go:59:18:59:47 | call to Get | EndToEnd.go:59:18:59:25 | selection of Params | EndToEnd.go:59:18:59:47 | call to Get | This path depends on a $@. | EndToEnd.go:59:18:59:25 | selection of Params | user-provided value |
|
||||
| EndToEnd.go:65:26:65:55 | call to Get | EndToEnd.go:65:26:65:33 | selection of Params | EndToEnd.go:65:26:65:55 | call to Get | This path depends on a $@. | EndToEnd.go:65:26:65:33 | selection of Params | user-provided value |
|
||||
| EndToEnd.go:58:18:58:47 | call to Get | EndToEnd.go:58:18:58:25 | selection of Params | EndToEnd.go:58:18:58:47 | call to Get | This path depends on a $@. | EndToEnd.go:58:18:58:25 | selection of Params | user-provided value |
|
||||
| EndToEnd.go:64:26:64:55 | call to Get | EndToEnd.go:64:26:64:33 | selection of Params | EndToEnd.go:64:26:64:55 | call to Get | This path depends on a $@. | EndToEnd.go:64:26:64:33 | selection of Params | user-provided value |
|
||||
edges
|
||||
| EndToEnd.go:59:18:59:25 | selection of Params | EndToEnd.go:59:18:59:30 | selection of Form | provenance | Src:MaD:3 |
|
||||
| EndToEnd.go:59:18:59:30 | selection of Form | EndToEnd.go:59:18:59:47 | call to Get | provenance | MaD:4 Sink:MaD:2 |
|
||||
| EndToEnd.go:65:26:65:33 | selection of Params | EndToEnd.go:65:26:65:38 | selection of Form | provenance | Src:MaD:3 |
|
||||
| EndToEnd.go:65:26:65:38 | selection of Form | EndToEnd.go:65:26:65:55 | call to Get | provenance | MaD:4 Sink:MaD:1 |
|
||||
| EndToEnd.go:58:18:58:25 | selection of Params | EndToEnd.go:58:18:58:30 | selection of Form | provenance | Src:MaD:3 |
|
||||
| EndToEnd.go:58:18:58:30 | selection of Form | EndToEnd.go:58:18:58:47 | call to Get | provenance | MaD:4 Sink:MaD:2 |
|
||||
| EndToEnd.go:64:26:64:33 | selection of Params | EndToEnd.go:64:26:64:38 | selection of Form | provenance | Src:MaD:3 |
|
||||
| EndToEnd.go:64:26:64:38 | selection of Form | EndToEnd.go:64:26:64:55 | call to Get | provenance | MaD:4 Sink:MaD:1 |
|
||||
models
|
||||
| 1 | Sink: group:revel; Controller; true; RenderFileName; ; ; Argument[0]; path-injection; manual |
|
||||
| 2 | Sink: os; ; false; Open; ; ; Argument[0]; path-injection; manual |
|
||||
| 3 | Source: group:revel; Controller; true; Params; ; ; ; remote; manual |
|
||||
| 4 | Summary: net/url; Values; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual |
|
||||
nodes
|
||||
| EndToEnd.go:59:18:59:25 | selection of Params | semmle.label | selection of Params |
|
||||
| EndToEnd.go:59:18:59:30 | selection of Form | semmle.label | selection of Form |
|
||||
| EndToEnd.go:59:18:59:47 | call to Get | semmle.label | call to Get |
|
||||
| EndToEnd.go:65:26:65:33 | selection of Params | semmle.label | selection of Params |
|
||||
| EndToEnd.go:65:26:65:38 | selection of Form | semmle.label | selection of Form |
|
||||
| EndToEnd.go:65:26:65:55 | call to Get | semmle.label | call to Get |
|
||||
| EndToEnd.go:58:18:58:25 | selection of Params | semmle.label | selection of Params |
|
||||
| EndToEnd.go:58:18:58:30 | selection of Form | semmle.label | selection of Form |
|
||||
| EndToEnd.go:58:18:58:47 | call to Get | semmle.label | call to Get |
|
||||
| EndToEnd.go:64:26:64:33 | selection of Params | semmle.label | selection of Params |
|
||||
| EndToEnd.go:64:26:64:38 | selection of Form | semmle.label | selection of Form |
|
||||
| EndToEnd.go:64:26:64:55 | call to Get | semmle.label | call to Get |
|
||||
subpaths
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: Security/CWE-022/TaintedPath.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -33,11 +33,11 @@ func init() {
|
||||
switch event {
|
||||
case revel.ENGINE_BEFORE_INITIALIZED:
|
||||
revel.AddHTTPMux("/this/is/a/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, "Hi there, it worked", r.URL.Path) // $ responsebody='selection of Path' responsebody='"Hi there, it worked"' Alert[go/reflected-xss]
|
||||
fmt.Fprintln(w, "Hi there, it worked", r.URL.Path) // $ responsebody='selection of Path' responsebody='"Hi there, it worked"'
|
||||
w.WriteHeader(200)
|
||||
}))
|
||||
revel.AddHTTPMux("/this/is/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, "Hi there, shorter prefix", r.URL.Path) // $ responsebody='selection of Path' responsebody='"Hi there, shorter prefix"' Alert[go/reflected-xss]
|
||||
fmt.Fprintln(w, "Hi there, shorter prefix", r.URL.Path) // $ responsebody='selection of Path' responsebody='"Hi there, shorter prefix"'
|
||||
w.WriteHeader(200)
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: Security/CWE-918/RequestForgery.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
client := notes.NewNotesServiceProtobufClient("http://localhost:8000", &http.Client{}) // $ ssrfSink
|
||||
client := notes.NewNotesServiceProtobufClient("http://localhost:8000", &http.Client{}) // test: ssrfSink
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Note struct { // $ message
|
||||
type Note struct { // test: message
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
@@ -83,7 +83,7 @@ func (x *Note) GetCreatedAt() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
type CreateNoteParams struct { // $ message
|
||||
type CreateNoteParams struct { // test: message
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
@@ -130,7 +130,7 @@ func (x *CreateNoteParams) GetText() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type GetAllNotesParams struct { // $ message
|
||||
type GetAllNotesParams struct { // test: message
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
@@ -168,7 +168,7 @@ func (*GetAllNotesParams) Descriptor() ([]byte, []int) {
|
||||
return file_rpc_notes_service_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
type GetAllNotesResult struct { // $ message
|
||||
type GetAllNotesResult struct { // test: message
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
@@ -340,7 +340,7 @@ func file_rpc_notes_service_proto_init() {
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{} // $ SPURIOUS: message // not message
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
|
||||
@@ -31,7 +31,7 @@ const _ = twirp.TwirpPackageMinVersion_8_1_0
|
||||
// NotesService Interface
|
||||
// ======================
|
||||
|
||||
type NotesService interface { // $ serviceInterface
|
||||
type NotesService interface { // test: serviceInterface
|
||||
CreateNote(context.Context, *CreateNoteParams) (*Note, error)
|
||||
|
||||
GetAllNotes(context.Context, *GetAllNotesParams) (*GetAllNotesResult, error)
|
||||
@@ -41,7 +41,7 @@ type NotesService interface { // $ serviceInterface
|
||||
// NotesService Protobuf Client
|
||||
// ============================
|
||||
|
||||
type notesServiceProtobufClient struct { // $ serviceClient
|
||||
type notesServiceProtobufClient struct { // test: serviceClient
|
||||
client HTTPClient
|
||||
urls [2]string
|
||||
interceptor twirp.Interceptor
|
||||
@@ -50,7 +50,7 @@ type notesServiceProtobufClient struct { // $ serviceClient
|
||||
|
||||
// NewNotesServiceProtobufClient creates a Protobuf client that implements the NotesService interface.
|
||||
// It communicates using Protobuf and can be configured with a custom HTTPClient.
|
||||
func NewNotesServiceProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) NotesService { // $ clientConstructor
|
||||
func NewNotesServiceProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) NotesService { // test: clientConstructor
|
||||
if c, ok := client.(*http.Client); ok {
|
||||
client = withoutRedirects(c)
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func NewNotesServiceProtobufClient(baseURL string, client HTTPClient, opts ...tw
|
||||
}
|
||||
}
|
||||
|
||||
func (c *notesServiceProtobufClient) CreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // not handler
|
||||
func (c *notesServiceProtobufClient) CreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // test: !handler
|
||||
ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes")
|
||||
ctx = ctxsetters.WithServiceName(ctx, "NotesService")
|
||||
ctx = ctxsetters.WithMethodName(ctx, "CreateNote")
|
||||
@@ -113,7 +113,7 @@ func (c *notesServiceProtobufClient) CreateNote(ctx context.Context, in *CreateN
|
||||
return caller(ctx, in)
|
||||
}
|
||||
|
||||
func (c *notesServiceProtobufClient) callCreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // not handler
|
||||
func (c *notesServiceProtobufClient) callCreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // test: !handler
|
||||
out := new(Note)
|
||||
ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out)
|
||||
if err != nil {
|
||||
@@ -130,7 +130,7 @@ func (c *notesServiceProtobufClient) callCreateNote(ctx context.Context, in *Cre
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *notesServiceProtobufClient) GetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // not handler
|
||||
func (c *notesServiceProtobufClient) GetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // test: !handler
|
||||
ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes")
|
||||
ctx = ctxsetters.WithServiceName(ctx, "NotesService")
|
||||
ctx = ctxsetters.WithMethodName(ctx, "GetAllNotes")
|
||||
@@ -159,7 +159,7 @@ func (c *notesServiceProtobufClient) GetAllNotes(ctx context.Context, in *GetAll
|
||||
return caller(ctx, in)
|
||||
}
|
||||
|
||||
func (c *notesServiceProtobufClient) callGetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // not handler
|
||||
func (c *notesServiceProtobufClient) callGetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // test: !handler
|
||||
out := new(GetAllNotesResult)
|
||||
ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out)
|
||||
if err != nil {
|
||||
@@ -180,7 +180,7 @@ func (c *notesServiceProtobufClient) callGetAllNotes(ctx context.Context, in *Ge
|
||||
// NotesService JSON Client
|
||||
// ========================
|
||||
|
||||
type notesServiceJSONClient struct { // $ serviceClient
|
||||
type notesServiceJSONClient struct { // test: serviceClient
|
||||
client HTTPClient
|
||||
urls [2]string
|
||||
interceptor twirp.Interceptor
|
||||
@@ -189,7 +189,7 @@ type notesServiceJSONClient struct { // $ serviceClient
|
||||
|
||||
// NewNotesServiceJSONClient creates a JSON client that implements the NotesService interface.
|
||||
// It communicates using JSON and can be configured with a custom HTTPClient.
|
||||
func NewNotesServiceJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) NotesService { // $ clientConstructor
|
||||
func NewNotesServiceJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) NotesService { // test: clientConstructor
|
||||
if c, ok := client.(*http.Client); ok {
|
||||
client = withoutRedirects(c)
|
||||
}
|
||||
@@ -223,7 +223,7 @@ func NewNotesServiceJSONClient(baseURL string, client HTTPClient, opts ...twirp.
|
||||
}
|
||||
}
|
||||
|
||||
func (c *notesServiceJSONClient) CreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // not handler
|
||||
func (c *notesServiceJSONClient) CreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // test: !handler
|
||||
ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes")
|
||||
ctx = ctxsetters.WithServiceName(ctx, "NotesService")
|
||||
ctx = ctxsetters.WithMethodName(ctx, "CreateNote")
|
||||
@@ -252,7 +252,7 @@ func (c *notesServiceJSONClient) CreateNote(ctx context.Context, in *CreateNoteP
|
||||
return caller(ctx, in)
|
||||
}
|
||||
|
||||
func (c *notesServiceJSONClient) callCreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // not handler
|
||||
func (c *notesServiceJSONClient) callCreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // test: !handler
|
||||
out := new(Note)
|
||||
ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out)
|
||||
if err != nil {
|
||||
@@ -269,7 +269,7 @@ func (c *notesServiceJSONClient) callCreateNote(ctx context.Context, in *CreateN
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *notesServiceJSONClient) GetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // not handler
|
||||
func (c *notesServiceJSONClient) GetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // test: !handler
|
||||
ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes")
|
||||
ctx = ctxsetters.WithServiceName(ctx, "NotesService")
|
||||
ctx = ctxsetters.WithMethodName(ctx, "GetAllNotes")
|
||||
@@ -298,7 +298,7 @@ func (c *notesServiceJSONClient) GetAllNotes(ctx context.Context, in *GetAllNote
|
||||
return caller(ctx, in)
|
||||
}
|
||||
|
||||
func (c *notesServiceJSONClient) callGetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // not handler
|
||||
func (c *notesServiceJSONClient) callGetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // test: !handler
|
||||
out := new(GetAllNotesResult)
|
||||
ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out)
|
||||
if err != nil {
|
||||
@@ -319,7 +319,7 @@ func (c *notesServiceJSONClient) callGetAllNotes(ctx context.Context, in *GetAll
|
||||
// NotesService Server Handler
|
||||
// ===========================
|
||||
|
||||
type notesServiceServer struct { // $ serviceServer
|
||||
type notesServiceServer struct { // test: serviceServer
|
||||
NotesService
|
||||
interceptor twirp.Interceptor
|
||||
hooks *twirp.ServerHooks
|
||||
@@ -331,7 +331,7 @@ type notesServiceServer struct { // $ serviceServer
|
||||
// NewNotesServiceServer builds a TwirpServer that can be used as an http.Handler to handle
|
||||
// HTTP requests that are routed to the right method in the provided svc implementation.
|
||||
// The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks).
|
||||
func NewNotesServiceServer(svc NotesService, opts ...interface{}) TwirpServer { // $ serverConstructor
|
||||
func NewNotesServiceServer(svc NotesService, opts ...interface{}) TwirpServer { // test: serverConstructor
|
||||
serverOpts := newServerOpts(opts)
|
||||
|
||||
// Using ReadOpt allows backwards and forwards compatibility with new options in the future
|
||||
@@ -535,7 +535,7 @@ func (s *notesServiceServer) serveCreateNoteProtobuf(ctx context.Context, resp h
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(req.Body) // $ Source
|
||||
buf, err := io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
s.handleRequestBodyError(ctx, resp, "failed to read request body", err)
|
||||
return
|
||||
@@ -812,7 +812,7 @@ func (s *notesServiceServer) PathPrefix() string {
|
||||
// automatically disabled if *(net/http).Client is passed to client
|
||||
// constructors. See the withoutRedirects function in this file for more
|
||||
// details.
|
||||
type HTTPClient interface { // $ SPURIOUS: serviceInterface // not serviceInterface
|
||||
type HTTPClient interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
@@ -820,7 +820,7 @@ type HTTPClient interface { // $ SPURIOUS: serviceInterface // not serviceInterf
|
||||
// HTTP handlers with additional methods for accessing metadata about the
|
||||
// service. Those accessors are a low-level API for building reflection tools.
|
||||
// Most people can think of TwirpServers as just http.Handlers.
|
||||
type TwirpServer interface { // $ SPURIOUS: serviceInterface // not serviceInterface
|
||||
type TwirpServer interface {
|
||||
http.Handler
|
||||
|
||||
// ServiceDescriptor returns gzipped bytes describing the .proto file that
|
||||
|
||||
@@ -16,7 +16,7 @@ type notesService struct {
|
||||
CurrentId int32
|
||||
}
|
||||
|
||||
func (s *notesService) CreateNote(ctx context.Context, params *notes.CreateNoteParams) (*notes.Note, error) { // $ Source request handler // route handler
|
||||
func (s *notesService) CreateNote(ctx context.Context, params *notes.CreateNoteParams) (*notes.Note, error) { // test: routeHandler, request
|
||||
if len(params.Text) < 4 {
|
||||
return nil, twirp.InvalidArgument.Error("Text should be min 4 characters.")
|
||||
}
|
||||
@@ -27,8 +27,8 @@ func (s *notesService) CreateNote(ctx context.Context, params *notes.CreateNoteP
|
||||
CreatedAt: time.Now().UnixMilli(),
|
||||
}
|
||||
|
||||
notes.NewNotesServiceProtobufClient(params.Text, &http.Client{}) // $ Alert ssrfSink ssrf
|
||||
notes.NewNotesServiceProtobufClient(strconv.FormatInt(int64(s.CurrentId), 10), &http.Client{}) // $ ssrfSink // not ssrf
|
||||
notes.NewNotesServiceProtobufClient(params.Text, &http.Client{}) // test: ssrfSink, ssrf
|
||||
notes.NewNotesServiceProtobufClient(strconv.FormatInt(int64(s.CurrentId), 10), &http.Client{}) // test: ssrfSink, !ssrf
|
||||
|
||||
s.Notes = append(s.Notes, note)
|
||||
|
||||
@@ -37,7 +37,7 @@ func (s *notesService) CreateNote(ctx context.Context, params *notes.CreateNoteP
|
||||
return ¬e, nil
|
||||
}
|
||||
|
||||
func (s *notesService) GetAllNotes(ctx context.Context, params *notes.GetAllNotesParams) (*notes.GetAllNotesResult, error) { // $ request handler // route handler
|
||||
func (s *notesService) GetAllNotes(ctx context.Context, params *notes.GetAllNotesParams) (*notes.GetAllNotesResult, error) { // test: routeHandler, request
|
||||
allNotes := make([]*notes.Note, 0)
|
||||
|
||||
fmt.Println(params)
|
||||
@@ -57,7 +57,7 @@ func main() {
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle(notesServer.PathPrefix(), notesServer)
|
||||
|
||||
err := http.ListenAndServe(":8000", notesServer) // not ssrfSink
|
||||
err := http.ListenAndServe(":8000", notesServer) // test: !ssrfSink
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -1,2 +1,32 @@
|
||||
invalidModelRow
|
||||
testFailures
|
||||
passingPositiveTests
|
||||
| PASSED | clientConstructor | rpc/notes/service.twirp.go:53:114:53:139 | comment |
|
||||
| PASSED | clientConstructor | rpc/notes/service.twirp.go:192:110:192:135 | comment |
|
||||
| PASSED | message | rpc/notes/service.pb.go:23:20:23:35 | comment |
|
||||
| PASSED | message | rpc/notes/service.pb.go:86:32:86:47 | comment |
|
||||
| PASSED | message | rpc/notes/service.pb.go:133:33:133:48 | comment |
|
||||
| PASSED | message | rpc/notes/service.pb.go:171:33:171:48 | comment |
|
||||
| PASSED | request | server/main.go:19:111:19:140 | comment |
|
||||
| PASSED | request | server/main.go:40:126:40:155 | comment |
|
||||
| PASSED | serverConstructor | rpc/notes/service.twirp.go:334:81:334:106 | comment |
|
||||
| PASSED | serviceClient | rpc/notes/service.twirp.go:44:42:44:63 | comment |
|
||||
| PASSED | serviceClient | rpc/notes/service.twirp.go:183:38:183:59 | comment |
|
||||
| PASSED | serviceInterface | rpc/notes/service.twirp.go:34:31:34:55 | comment |
|
||||
| PASSED | serviceServer | rpc/notes/service.twirp.go:322:34:322:55 | comment |
|
||||
| PASSED | ssrf | server/main.go:30:97:30:119 | comment |
|
||||
| PASSED | ssrfSink | client/main.go:12:89:12:105 | comment |
|
||||
| PASSED | ssrfSink | server/main.go:30:97:30:119 | comment |
|
||||
| PASSED | ssrfSink | server/main.go:31:97:31:120 | comment |
|
||||
failingPositiveTests
|
||||
passingNegativeTests
|
||||
| PASSED | !handler | rpc/notes/service.twirp.go:87:109:87:125 | comment |
|
||||
| PASSED | !handler | rpc/notes/service.twirp.go:116:113:116:129 | comment |
|
||||
| PASSED | !handler | rpc/notes/service.twirp.go:133:124:133:140 | comment |
|
||||
| PASSED | !handler | rpc/notes/service.twirp.go:162:128:162:144 | comment |
|
||||
| PASSED | !handler | rpc/notes/service.twirp.go:226:105:226:121 | comment |
|
||||
| PASSED | !handler | rpc/notes/service.twirp.go:255:109:255:125 | comment |
|
||||
| PASSED | !handler | rpc/notes/service.twirp.go:272:120:272:136 | comment |
|
||||
| PASSED | !handler | rpc/notes/service.twirp.go:301:124:301:140 | comment |
|
||||
| PASSED | !ssrf | server/main.go:31:97:31:120 | comment |
|
||||
| PASSED | !ssrfSink | server/main.go:60:51:60:68 | comment |
|
||||
failingNegativeTests
|
||||
|
||||
@@ -2,76 +2,181 @@ import go
|
||||
import semmle.go.dataflow.ExternalFlow
|
||||
import ModelValidation
|
||||
import semmle.go.security.RequestForgery
|
||||
import utils.test.InlineExpectationsTest
|
||||
|
||||
module TwirpTest implements TestSig {
|
||||
string getARelevantTag() {
|
||||
result =
|
||||
[
|
||||
"handler", "request", "ssrfSink", "message", "serviceInterface", "serviceClient",
|
||||
"serviceServer", "clientConstructor", "serverConstructor", "ssrf"
|
||||
]
|
||||
class InlineTest extends LineComment {
|
||||
string tests;
|
||||
|
||||
InlineTest() { tests = this.getText().regexpCapture("\\s*test:(.*)", 1) }
|
||||
|
||||
string getPositiveTest() {
|
||||
result = tests.trim().splitAt(",").trim() and not result.matches("!%")
|
||||
}
|
||||
|
||||
additional predicate hasEntityResult(Location location, string element, Entity entity) {
|
||||
location = entity.getDeclaration().getLocation() and
|
||||
element = entity.toString()
|
||||
string getNegativeTest() { result = tests.trim().splitAt(",").trim() and result.matches("!%") }
|
||||
|
||||
predicate hasPositiveTest(string test) { test = this.getPositiveTest() }
|
||||
|
||||
predicate hasNegativeTest(string test) { test = this.getNegativeTest() }
|
||||
|
||||
predicate inNode(DataFlow::Node n) {
|
||||
this.getLocation().getFile() = n.getFile() and
|
||||
this.getLocation().getStartLine() = n.getStartLine()
|
||||
}
|
||||
|
||||
additional predicate hasTypeResult(Location location, string element, Type goType) {
|
||||
exists(TypeEntity typeEntity |
|
||||
typeEntity.getType() = goType and
|
||||
location = typeEntity.getDeclaration().getLocation() and
|
||||
element = goType.toString()
|
||||
)
|
||||
predicate inEntity(Entity e) {
|
||||
this.getLocation().getFile() = e.getDeclaration().getFile() and
|
||||
this.getLocation().getStartLine() = e.getDeclaration().getLocation().getStartLine()
|
||||
}
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
value = "" and
|
||||
(
|
||||
tag = "handler" and
|
||||
exists(Twirp::ServiceHandler handler | hasEntityResult(location, element, handler))
|
||||
or
|
||||
tag = "request" and
|
||||
exists(Twirp::Request request |
|
||||
location = request.getLocation() and
|
||||
element = request.toString()
|
||||
)
|
||||
or
|
||||
tag = "ssrfSink" and
|
||||
exists(RequestForgery::Sink sink |
|
||||
location = sink.getLocation() and
|
||||
element = sink.toString()
|
||||
)
|
||||
or
|
||||
tag = "message" and
|
||||
exists(Twirp::ProtobufMessageType message | hasTypeResult(location, element, message))
|
||||
or
|
||||
tag = "serviceInterface" and
|
||||
exists(Twirp::ServiceInterfaceType serviceInterface |
|
||||
hasTypeResult(location, element, serviceInterface.getDefinedType())
|
||||
)
|
||||
or
|
||||
tag = "serviceClient" and
|
||||
exists(Twirp::ServiceClientType client | hasTypeResult(location, element, client))
|
||||
or
|
||||
tag = "serviceServer" and
|
||||
exists(Twirp::ServiceServerType server | hasTypeResult(location, element, server))
|
||||
or
|
||||
tag = "clientConstructor" and
|
||||
exists(Twirp::ClientConstructor constructor | hasEntityResult(location, element, constructor))
|
||||
or
|
||||
tag = "serverConstructor" and
|
||||
exists(Twirp::ServerConstructor constructor | hasEntityResult(location, element, constructor))
|
||||
or
|
||||
tag = "ssrf" and
|
||||
exists(DataFlow::Node sink |
|
||||
RequestForgery::Flow::flowTo(sink) and
|
||||
location = sink.getLocation() and
|
||||
element = sink.toString()
|
||||
)
|
||||
predicate inType(Type t) {
|
||||
exists(TypeEntity te |
|
||||
te.getType() = t and
|
||||
this.getLocation().getFile() = te.getDeclaration().getFile() and
|
||||
this.getLocation().getStartLine() = te.getDeclaration().getLocation().getStartLine()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<TwirpTest>
|
||||
query predicate passingPositiveTests(string res, string expectation, InlineTest t) {
|
||||
res = "PASSED" and
|
||||
t.hasPositiveTest(expectation) and
|
||||
(
|
||||
expectation = "handler" and
|
||||
exists(Twirp::ServiceHandler n | t.inEntity(n))
|
||||
or
|
||||
expectation = "request" and
|
||||
exists(Twirp::Request n | t.inNode(n))
|
||||
or
|
||||
expectation = "ssrfSink" and
|
||||
exists(RequestForgery::Sink n | t.inNode(n))
|
||||
or
|
||||
expectation = "message" and
|
||||
exists(Twirp::ProtobufMessageType n | t.inType(n))
|
||||
or
|
||||
expectation = "serviceInterface" and
|
||||
exists(Twirp::ServiceInterfaceType n | t.inType(n.getDefinedType()))
|
||||
or
|
||||
expectation = "serviceClient" and
|
||||
exists(Twirp::ServiceClientType n | t.inType(n))
|
||||
or
|
||||
expectation = "serviceServer" and
|
||||
exists(Twirp::ServiceServerType n | t.inType(n))
|
||||
or
|
||||
expectation = "clientConstructor" and
|
||||
exists(Twirp::ClientConstructor n | t.inEntity(n))
|
||||
or
|
||||
expectation = "serverConstructor" and
|
||||
exists(Twirp::ServerConstructor n | t.inEntity(n))
|
||||
or
|
||||
expectation = "ssrf" and
|
||||
exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink))
|
||||
)
|
||||
}
|
||||
|
||||
query predicate failingPositiveTests(string res, string expectation, InlineTest t) {
|
||||
res = "FAILED" and
|
||||
t.hasPositiveTest(expectation) and
|
||||
(
|
||||
expectation = "handler" and
|
||||
not exists(Twirp::ServiceHandler n | t.inEntity(n))
|
||||
or
|
||||
expectation = "request" and
|
||||
not exists(Twirp::Request n | t.inNode(n))
|
||||
or
|
||||
expectation = "ssrfSink" and
|
||||
not exists(RequestForgery::Sink n | t.inNode(n))
|
||||
or
|
||||
expectation = "message" and
|
||||
not exists(Twirp::ProtobufMessageType n | t.inType(n))
|
||||
or
|
||||
expectation = "serviceInterface" and
|
||||
not exists(Twirp::ServiceInterfaceType n | t.inType(n.getDefinedType()))
|
||||
or
|
||||
expectation = "serviceClient" and
|
||||
not exists(Twirp::ServiceClientType n | t.inType(n))
|
||||
or
|
||||
expectation = "serviceServer" and
|
||||
not exists(Twirp::ServiceServerType n | t.inType(n))
|
||||
or
|
||||
expectation = "clientConstructor" and
|
||||
not exists(Twirp::ClientConstructor n | t.inEntity(n))
|
||||
or
|
||||
expectation = "serverConstructor" and
|
||||
not exists(Twirp::ServerConstructor n | t.inEntity(n))
|
||||
or
|
||||
expectation = "ssrf" and
|
||||
not exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink))
|
||||
)
|
||||
}
|
||||
|
||||
query predicate passingNegativeTests(string res, string expectation, InlineTest t) {
|
||||
res = "PASSED" and
|
||||
t.hasNegativeTest(expectation) and
|
||||
(
|
||||
expectation = "!handler" and
|
||||
not exists(Twirp::ServiceHandler n | t.inEntity(n))
|
||||
or
|
||||
expectation = "!request" and
|
||||
not exists(Twirp::Request n | t.inNode(n))
|
||||
or
|
||||
expectation = "!ssrfSink" and
|
||||
not exists(RequestForgery::Sink n | t.inNode(n))
|
||||
or
|
||||
expectation = "!message" and
|
||||
not exists(Twirp::ProtobufMessageType n | t.inType(n))
|
||||
or
|
||||
expectation = "!serviceInterface" and
|
||||
not exists(Twirp::ServiceInterfaceType n | t.inType(n))
|
||||
or
|
||||
expectation = "!serviceClient" and
|
||||
not exists(Twirp::ServiceClientType n | t.inType(n))
|
||||
or
|
||||
expectation = "!serviceServer" and
|
||||
not exists(Twirp::ServiceServerType n | t.inType(n))
|
||||
or
|
||||
expectation = "!clientConstructor" and
|
||||
not exists(Twirp::ClientConstructor n | t.inEntity(n))
|
||||
or
|
||||
expectation = "!serverConstructor" and
|
||||
not exists(Twirp::ServerConstructor n | t.inEntity(n))
|
||||
or
|
||||
expectation = "!ssrf" and
|
||||
not exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink))
|
||||
)
|
||||
}
|
||||
|
||||
query predicate failingNegativeTests(string res, string expectation, InlineTest t) {
|
||||
res = "FAILED" and
|
||||
t.hasNegativeTest(expectation) and
|
||||
(
|
||||
expectation = "!handler" and
|
||||
exists(Twirp::ServiceHandler n | t.inEntity(n))
|
||||
or
|
||||
expectation = "!request" and
|
||||
exists(Twirp::Request n | t.inNode(n))
|
||||
or
|
||||
expectation = "!ssrfSink" and
|
||||
exists(RequestForgery::Sink n | t.inNode(n))
|
||||
or
|
||||
expectation = "!message" and
|
||||
exists(Twirp::ProtobufMessageType n | t.inType(n))
|
||||
or
|
||||
expectation = "!serviceInterface" and
|
||||
exists(Twirp::ServiceInterfaceType n | t.inType(n))
|
||||
or
|
||||
expectation = "!serviceClient" and
|
||||
exists(Twirp::ServiceClientType n | t.inType(n))
|
||||
or
|
||||
expectation = "!serviceServer" and
|
||||
exists(Twirp::ServiceServerType n | t.inType(n))
|
||||
or
|
||||
expectation = "!clientConstructor" and
|
||||
exists(Twirp::ClientConstructor n | t.inEntity(n))
|
||||
or
|
||||
expectation = "!serverConstructor" and
|
||||
exists(Twirp::ServerConstructor n | t.inEntity(n))
|
||||
or
|
||||
expectation = "!ssrf" and
|
||||
exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: Security/CWE-079/ReflectedXss.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
query: Security/CWE-089/SqlInjection.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -9,50 +9,50 @@ import (
|
||||
|
||||
func test(request *http.Request, writer http.ResponseWriter) {
|
||||
|
||||
param1 := request.URL.Query().Get("param1") // $ Source[go/reflected-xss]
|
||||
param1 := request.URL.Query().Get("param1")
|
||||
writer.Write([]byte(html.EscapeString(param1))) // GOOD: escaped.
|
||||
|
||||
writer.Write([]byte(html.UnescapeString(param1))) // $ Alert[go/reflected-xss] // BAD: unescaped.
|
||||
writer.Write([]byte(html.UnescapeString(param1))) // BAD: unescaped.
|
||||
|
||||
node, _ := html.Parse(request.Body) // $ Source[go/reflected-xss]
|
||||
writer.Write([]byte(node.Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data
|
||||
node, _ := html.Parse(request.Body)
|
||||
writer.Write([]byte(node.Data)) // BAD: writing unescaped HTML data
|
||||
|
||||
node2, _ := html.ParseWithOptions(request.Body) // $ Source[go/reflected-xss]
|
||||
writer.Write([]byte(node2.Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data
|
||||
node2, _ := html.ParseWithOptions(request.Body)
|
||||
writer.Write([]byte(node2.Data)) // BAD: writing unescaped HTML data
|
||||
|
||||
nodes, _ := html.ParseFragment(request.Body, nil) // $ Source[go/reflected-xss]
|
||||
writer.Write([]byte(nodes[0].Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data
|
||||
nodes, _ := html.ParseFragment(request.Body, nil)
|
||||
writer.Write([]byte(nodes[0].Data)) // BAD: writing unescaped HTML data
|
||||
|
||||
nodes2, _ := html.ParseFragmentWithOptions(request.Body, nil) // $ Source[go/reflected-xss]
|
||||
writer.Write([]byte(nodes2[0].Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data
|
||||
nodes2, _ := html.ParseFragmentWithOptions(request.Body, nil)
|
||||
writer.Write([]byte(nodes2[0].Data)) // BAD: writing unescaped HTML data
|
||||
|
||||
html.Render(writer, node) // $ Alert[go/reflected-xss] // BAD: rendering untrusted HTML to `writer`
|
||||
html.Render(writer, node) // BAD: rendering untrusted HTML to `writer`
|
||||
|
||||
tokenizer := html.NewTokenizer(request.Body) // $ Source[go/reflected-xss]
|
||||
writer.Write(tokenizer.Buffered()) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data
|
||||
writer.Write(tokenizer.Raw()) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data
|
||||
tokenizer := html.NewTokenizer(request.Body)
|
||||
writer.Write(tokenizer.Buffered()) // BAD: writing unescaped HTML data
|
||||
writer.Write(tokenizer.Raw()) // BAD: writing unescaped HTML data
|
||||
_, value, _ := tokenizer.TagAttr()
|
||||
writer.Write(value) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data
|
||||
writer.Write(tokenizer.Text()) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data
|
||||
writer.Write([]byte(tokenizer.Token().Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data
|
||||
writer.Write(value) // BAD: writing unescaped HTML data
|
||||
writer.Write(tokenizer.Text()) // BAD: writing unescaped HTML data
|
||||
writer.Write([]byte(tokenizer.Token().Data)) // BAD: writing unescaped HTML data
|
||||
|
||||
tokenizerFragment := html.NewTokenizerFragment(request.Body, "some context") // $ Source[go/reflected-xss]
|
||||
writer.Write(tokenizerFragment.Buffered()) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data
|
||||
tokenizerFragment := html.NewTokenizerFragment(request.Body, "some context")
|
||||
writer.Write(tokenizerFragment.Buffered()) // BAD: writing unescaped HTML data
|
||||
|
||||
var cleanNode html.Node
|
||||
taintedNode, _ := html.Parse(request.Body) // $ Source[go/reflected-xss]
|
||||
taintedNode, _ := html.Parse(request.Body)
|
||||
cleanNode.AppendChild(taintedNode)
|
||||
html.Render(writer, &cleanNode) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data
|
||||
html.Render(writer, &cleanNode) // BAD: writing unescaped HTML data
|
||||
|
||||
var cleanNode2 html.Node
|
||||
taintedNode2, _ := html.Parse(request.Body) // $ Source[go/reflected-xss]
|
||||
taintedNode2, _ := html.Parse(request.Body)
|
||||
cleanNode2.InsertBefore(taintedNode2, &cleanNode2)
|
||||
html.Render(writer, &cleanNode2) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data
|
||||
html.Render(writer, &cleanNode2) // BAD: writing unescaped HTML data
|
||||
|
||||
}
|
||||
|
||||
func sqlTest(request *http.Request, db *sql.DB) {
|
||||
// Ensure EscapeString is a taint propagator for non-XSS queries, e.g. SQL injection:
|
||||
cookie, _ := request.Cookie("SomeCookie") // $ Source[go/sql-injection]
|
||||
db.Query(html.EscapeString(cookie.Value)) // $ Alert[go/sql-injection]
|
||||
cookie, _ := request.Cookie("SomeCookie")
|
||||
db.Query(html.EscapeString(cookie.Value))
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package main
|
||||
|
||||
func isPrefixOf(xs, ys []int) bool {
|
||||
for i := 0; i < len(xs); i++ {
|
||||
if len(ys) == 0 || xs[i] != ys[i] { // $ Alert // NOT OK
|
||||
if len(ys) == 0 || xs[i] != ys[i] { // NOT OK
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: InconsistentCode/ConstantLengthComparison.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
InconsistentCode/ConstantLengthComparison.ql
|
||||
|
||||
@@ -7,7 +7,7 @@ func zeroOutExceptBad(a []int, lower int, upper int) {
|
||||
}
|
||||
|
||||
// zero out everything above index `upper`
|
||||
for i := upper + 1; i < len(a); i-- { // $ Alert // NOT OK
|
||||
for i := upper + 1; i < len(a); i-- { // NOT OK
|
||||
a[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
query: InconsistentCode/InconsistentLoopOrientation.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
InconsistentCode/InconsistentLoopOrientation.ql
|
||||
|
||||
@@ -6,12 +6,12 @@ func f1(i int) {
|
||||
}
|
||||
|
||||
func f2(i int, s string) {
|
||||
for j := i + 1; j < len(s); j-- { // $ Alert // NOT OK
|
||||
for j := i + 1; j < len(s); j-- { // NOT OK
|
||||
}
|
||||
}
|
||||
|
||||
func f3(s string) {
|
||||
for i, l := 0, len(s); i > l; i++ { // $ Alert // NOT OK
|
||||
for i, l := 0, len(s); i > l; i++ { // NOT OK
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ func f4(lower int, a []int) {
|
||||
}
|
||||
|
||||
func f5(upper int, a []int) {
|
||||
for i := upper + 1; i < len(a); i-- { // $ Alert // NOT OK
|
||||
for i := upper + 1; i < len(a); i-- { // NOT OK
|
||||
a[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user