Compare commits

..

44 Commits

Author SHA1 Message Date
Copilot
b682877968 Python: simplify TBlockStmt char pred via exclusion list
Replace the 14-disjunct allow-list with a 2-conjunct exclusion list.
Of the 17 Py::StmtList getters in AstGenerated.qll, only Try.getHandlers()
and MatchStmt.getCases() should not be wrapped as BlockStmts (they are
iterated individually by the shared library's Try/Switch logic via
getCatch(int) and getCase(int)). All other StmtLists are imperative
block bodies.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-07 17:13:50 +00:00
Copilot
c9445f74c2 Python: introduce TStmt union via newtype-branch alias
Rename the TStmt newtype branch to TPyStmt, and add a private union
type alias

  private class TStmt = TPyStmt or TBlockStmt;

This lets the public Stmt class use TStmt directly in its extends
clause:

  class Stmt extends AstNodeImpl, TStmt { ... }

instead of the previous

  class Stmt extends AstNodeImpl {
    Stmt() { this instanceof TStmt or this instanceof TBlockStmt }
    ...
  }

The same pattern is used in cpp/.../TInstruction.qll and
rust/.../Synth.qll.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-07 17:08:10 +00:00
Copilot
ed1709eb4a Python: use private-abstract + final-alias pattern for AstNode
Convert AstNode from a concrete class with empty default predicates into
a private abstract class plus a final alias, matching the pattern used
in cpp/.../EdgeKind.qll and cpp/.../IRVariable.qll:

  abstract private class AstNodeImpl extends TAstNode {
    abstract string toString();
    abstract Py::Location getLocation();
    abstract Callable getEnclosingCallable();
    ...
  }

  final class AstNode = AstNodeImpl;

This makes the compiler enforce that every concrete subclass implements
toString/getLocation/getEnclosingCallable, replacing the brittle
'empty default + per-branch override' arrangement. Sister classes
inside the module now extend AstNodeImpl instead of AstNode (which is
final and cannot be extended).

The empty Parameter stub gains explicit none() overrides for the
three abstract members, since QL requires them statically even when
the class has no instances.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-07 16:58:43 +00:00
Copilot
00c742f5ff Python: document why Assignment subclasses are empty
Explain that the shared library's Assignment / CompoundAssignment
hierarchy extends BinaryExpr, so it cannot host Python's statement-
level assignment forms (Assign, AugAssign), and that Python has no
short-circuiting compound operators (&&=, ||=, ??=) so all
subclasses remain empty.

No behaviour change; doc comments only.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-07 14:14:16 +00:00
Copilot
06e9bbc3a6 Python: index TBlockStmt by Py::StmtList instead of (parent, slot)
Replace the two-key TBlockStmt(Py::AstNode parent, string slot) newtype
branch with the simpler TBlockStmt(Py::StmtList sl). Each Py::StmtList
that represents an imperative block (function/class/module body, if/
while/for branch, try/except/finally body, case body, except/except*
body) becomes one BlockStmt directly. The slot string disappears;
toString just defers to Py::StmtList.toString() ('StmtList').

The newtype branch keeps an explicit characteristic predicate listing
the slots that count as block bodies. This excludes Try.getHandlers(),
which is a Py::StmtList of ExceptStmt items already iterated by the
shared library's Try logic via getCatch(int) - including it would
produce parallel CFG edges (verified: a permissive
TBlockStmt(Py::StmtList sl) version regressed CPython to 1720
multipleSuccessors and 584 deadEnds before this restriction).

Drops the getBodyStmtList helper. Caller sites now use the StmtList
accessor directly: TBlockStmt(ifStmt.getBody()),
TBlockStmt(tryStmt.getFinalbody()), etc.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-07 12:54:02 +00:00
Copilot
250b63c216 Python: unify Py::BoolExpr handling via TBoolExprPair
Previously a Py::BoolExpr appeared in two newtype branches: as TExpr(be)
(the outermost pair) and TBoolExprPair(be, i) for inner pairs of 3+
operand expressions. This forced BinaryExpr/LogicalAndExpr/LogicalOrExpr
to disjoin two cases, and the synthetic-pair handling spanned multiple
layers.

Restrict TExpr to non-BoolExpr Py::Expr, and extend TBoolExprPair to
cover every operand pair (index 0..n-2). Now every Py::BoolExpr is
represented uniformly as TBoolExprPair(_, 0) for the whole expression
and TBoolExprPair(_, i) for inner pairs.

Extend AstNode.asExpr() to also recover the underlying Py::BoolExpr
from TBoolExprPair(_, 0). This makes asExpr() the inverse of
construction: every 'result = TExpr(e)' turns into 'result.asExpr() = e',
which works uniformly for BoolExprs and non-BoolExprs alike.

Consequences:

- BinaryExpr now extends TBoolExprPair directly with a single uniform
  rule for left/right operands.
- LogicalAndExpr/LogicalOrExpr are one-line char preds via
  getBoolExpr().
- The private BoolExprPair wrapper class folds into BinaryExpr.
- 60+ leaf wrappers now read 'result.asExpr() = py_expr' instead of
  'result = TExpr(py_expr)'.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-07 12:04:54 +00:00
Copilot
77e36d3cfa Python: merge T*AstNode wrappers into matching public classes
Five of the six per-newtype-branch wrapper classes had a natural
public class corresponding to that branch:

  TStmtAstNode      -> Stmt        (TStmt subset; BlockStmt overrides for TBlockStmt)
  TExprAstNode      -> Expr        (TExpr subset; BoolExprPair overrides for TBoolExprPair)
  TScopeAstNode     -> Callable    (= TScope exactly)
  TPatternAstNode   -> Pattern     (= TPattern exactly)
  TBlockStmtAstNode -> BlockStmt   (= TBlockStmt exactly)

Move toString/getLocation/getEnclosingCallable onto these classes and
delete the wrappers.

The sixth wrapper (TBoolExprPair) has no exact public counterpart -
BinaryExpr is broader, including TExpr-branch BoolExprs - so it
remains as a small private class, renamed BoolExprPair.

No behaviour change: all 24 NewCfg evaluation-order tests pass; all
11 shared-CFG consistency queries report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-07 11:31:07 +00:00
Copilot
f2151fe232 Python: dispatch toString/getLocation/getEnclosingCallable per branch
Replace the three big disjunctive predicates on AstNode with empty
defaults plus per-newtype-branch override classes:

  AstNode.toString()              { none() }
  AstNode.getLocation()           { none() }
  AstNode.getEnclosingCallable()  { none() }

Six private subclasses (one per newtype branch — TStmt, TExpr,
TScope, TPattern, TBoolExprPair, TBlockStmt) override these with
the branch-specific implementation. This mirrors the per-class
dispatch already used for getChild.

No behaviour change: all 24 NewCfg evaluation-order tests pass and
all 11 shared-CFG consistency queries still report 0 violations on
CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-07 11:06:40 +00:00
Copilot
9781ee8d66 Python: adapt to new shared CFG signature
Main added two new requirements to AstSig:
- A 'Parameter' class with a 'getDefaultValue()' method, plus a
  'callableGetParameter(Callable, int)' predicate.
- A 'CallableContext' class in InputSig1, replacing the previous
  'CallableBodyPartContext'.

Add stub implementations: 'Parameter' is empty (none()) and
'callableGetParameter' returns nothing, mirroring Java's TODO. Rename
'CallableBodyPartContext = Void' to 'CallableContext = Void' in the
Python Input module.

NewCfg evaluation-order tests still pass at the 22/24 baseline; all
11 shared-CFG consistency queries still report 0 violations on
CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-05 15:26:20 +00:00
Copilot
03b8e8fdde Python: refactor getChild into per-class OO dispatch
Replace the single ~240-line top-level getChild predicate with one
override per AST class. AstNode declares a default

  AstNode getChild(int index) { none() }

and each subclass with children overrides it (41 classes total).
The top-level predicate becomes a one-line dispatch:

  AstNode getChild(AstNode n, int index) { result = n.getChild(index) }

No behavioral change: NewCfg evaluation-order tests still pass at the
same 22/24 baseline, and all 11 shared-CFG consistency queries still
report 0 violations on CPython.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-05 15:21:43 +00:00
Copilot
93112b2b75 Python: include try-else in getChild for completion propagation
The shared CFG library propagates abrupt completions from child to
parent via getChild(parent, _) = child. Python's try.getElse() was
wired into normal step rules but not listed in getChild(TryStmt, ...),
so return/break/continue/raise statements occurring inside a try-else
block had no parent path and ended up as dead-end CFG nodes.

Add the else block at index -2 (alongside finally at -1). This affects
only completion propagation; the normal-flow CFG is unchanged because
TryStmt has explicit step rules.

Verified on a CPython database: all 11 shared-CFG consistency queries
now pass with 0 violations (deadEnd: 244 -> 0).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-05 15:21:43 +00:00
Copilot
76724c5391 Shared CFG: support for-else and while-else loops
Add two default predicates to AstSig:

  default AstNode getWhileElse(WhileStmt loop) { none() }
  default AstNode getForeachElse(ForeachStmt loop) { none() }

When defined, the explicit-step rules for While/Do and Foreach
route the loop's normal-completion exits through the else block
before reaching the after-loop node:

  - WhileStmt: after-false condition -> before-else -> after-while
    (instead of directly after-while).
  - ForeachStmt: after-collection [empty] and the LoopHeader exit
    are both routed through before-else -> after-foreach.

Python's Ast module overrides the predicates to return the
synthetic BlockStmt for the orelse slot, replacing the previous
customisations in Input::step. This eliminates parallel direct
successors emitted by the previous Python-side step additions
(verified: multipleSuccessors on a CPython database goes from
1340 to 0).

Java and C# CFG tests are unaffected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-05 15:21:43 +00:00
Copilot
edfe91832b Python: compact-renumber FunctionExpr/Lambda defaults
`Args.getDefault(int)` and `Args.getKwDefault(int)` are indexed by
argument position (with gaps for args without defaults), not by
default position. The CFG `getChild` predicate for FunctionDefExpr
and LambdaExpr therefore had gaps at low indices and collisions
where defaults and kwdefaults overlapped, producing parallel
edges before the FunctionExpr.

Use `rank` to compact-renumber `getDefault(n)` and `getKwDefault(n)`
in source order. Verified on a CPython database: removes ~536
`multipleSuccessors` consistency results (1340 -> 804); the rest are
`for/else` and `while/else`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-05 15:21:43 +00:00
Copilot
58cda914db Python: collapse two-layer AstNodeImpl into a single Ast module
Merge the previous `Ast` and `AstSigImpl` modules into a single
`module Ast implements AstSig<Py::Location>`. Classes now use the
signature names (IfStmt, WhileStmt, ForeachStmt, etc.) and signature
predicates (getCondition, getThen, getElse, etc.) directly, with no
intermediate renaming layer.

Drop the TStmtListNode newtype branch entirely. Replace it with a
synthetic TBlockStmt(parent, slot) keyed by a parent AST node and a
slot label string ('body', 'orelse', 'finally'). Py::StmtList no
longer appears in the newtype; the BlockStmt class provides indexed
access to the underlying body items via getStmt(n).

All 22 of 24 evaluation-order tests still pass; the same 2
comprehension-related failures predate this refactor.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-05 15:21:43 +00:00
yoff
0b4a24884f python: add consistency checks
Co-authored-by: aschackmull <aschackmull@github.com>
2026-05-05 15:21:42 +00:00
yoff
3b0abad701 Python: add pattern nodes
Co-authored-by: Copilot <copilot@github.com>
2026-05-05 15:21:42 +00:00
Taus
68b3d57563 Cleanup, printCFG
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:42 +00:00
Taus
a33b49a3f3 WIP2 2026-05-05 15:21:42 +00:00
Taus
1af415bec3 WIP 2026-05-05 15:21:42 +00:00
Taus
e3155ea544 Python: Handle dict unpacking in calls
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:42 +00:00
Taus
04b8c4bc7e Python: Fix exception issue
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:42 +00:00
Taus
f85b532bb3 Python: Fix match
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:42 +00:00
Taus
0e1f1d9f09 Python: Support match
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:42 +00:00
Taus
53da31bd15 Python: More nodes
Not entirely sure about the `else:` blocks.

Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:42 +00:00
Taus
1f82dbc583 Python: Comprehensions
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:41 +00:00
Taus
b229066891 Python: Add with
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:41 +00:00
Taus
0acbb12fb9 Python: More simple statements
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:41 +00:00
Taus
542efce4a6 Python: assignments
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:41 +00:00
Taus
2db400aebd Python: Attributes
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:41 +00:00
Taus
66bbb60614 Python: Function calls
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:41 +00:00
Taus
971beb2d89 Python: Assert statements
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:41 +00:00
Taus
ea204ac75f Python: Support various literals
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:41 +00:00
Taus
3be562929a Python: Ignore synthetic CFG nodes
We can only annotate the ones that correspond directly to AST nodes
anyway.

Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:41 +00:00
Taus
dc0344e2fc Python: More AstNodeImpl improvements
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:41 +00:00
Taus
2ed75e7ca7 Python: Instantiate CFG tests with new CFG library
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:40 +00:00
Taus
9974584102 Python: Instantiate CFG module fully
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:40 +00:00
Taus
6086b999f6 Python: Use fields everywhere in new AST classes
Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:40 +00:00
Taus
d62e116fc2 Python: First stab at shared control-flow 2026-05-05 15:21:40 +00:00
Taus
4582855de1 Python: Make CFG tests parameterised
Currently we only instantiate them with the old CFG library, but in the
future we'll want to do this with the new library as well.

Co-authored-by: yoff <yoff@github.com>
2026-05-05 15:21:40 +00:00
Taus
ba29e7e34d Python: Add ConsecutiveTimestamps test
This one is potentially a bit iffy -- it checks for a very powerful
propetry (that implies many of the other queries), but as the test
results show, it can produce false positives when there is in fact no
problem. We may want to get rid of it entirely, if it becomes too noisy.
2026-05-05 15:21:40 +00:00
Taus
f97bf38f3b Python: Add NeverReachable test
This looks for nodes annotated with `t.never` in the test that are
reachable in the CFG. This should not happen (it messes with various
queries, e.g. the "mixed returns" query), but the test shows that in a
few particular cases (involving the `match` statement where all cases
contain `return`s), we _do_ have reachable nodes that shouldn't be.
2026-05-05 15:21:40 +00:00
Taus
a8d136d3d6 Python: Add BasicBlockOrdering test
This one demonstrates a bug in the current CFG. In a dictionary
comprehension `{k: v for k, v in d.items()}`, we evaluate the value
before the key, which is incorrect. (A fix for this bug has been
implemented in a separate PR.)
2026-05-05 15:21:40 +00:00
Taus
710a43ac7f Python: Add some CFG-validation queries
These use the annotated, self-verifying test files to check various
consistency requirements.

Some of these may be expressing the same thing in different ways, but
it's fairly cheap to keep them around, so I have not attempted to
produce a minimal set of queries for this.
2026-05-05 15:21:40 +00:00
Taus
3402d0eaeb Python: Add self-validating CFG tests
These tests consist of various Python constructions (hopefully a
somewhat comprehensive set) with specific timestamp annotations
scattered throughout. When the tests are run using the Python 3
interpreter, these annotations are checked and compared to the "current
timestamp" to see that they are in agreement. This is what makes the
tests "self-validating".

There are a few different kinds of annotations: the basic `t[4]` style
(meaning this is executed at timestamp 4), the `t.dead[4]` variant
(meaning this _would_ happen at timestamp 4, but it is in a dead
branch), and `t.never` (meaning this is never executed at all).

In addition to this, there is a query, MissingAnnotations, which checks
whether we have applied these annotations maximally. Many expression
nodes are not actually annotatable, so there is a sizeable list of
excluded nodes for that query.
2026-05-05 15:21:39 +00:00
2956 changed files with 24503 additions and 110315 deletions

View File

@@ -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

View File

@@ -70,7 +70,7 @@ jobs:
SHORTNAME=`basename $DATABASE` SHORTNAME=`basename $DATABASE`
python misc/scripts/models-as-data/generate_mad.py --language java --with-summaries --with-sinks $DATABASE $SHORTNAME/$QL_VARIANT python misc/scripts/models-as-data/generate_mad.py --language java --with-summaries --with-sinks $DATABASE $SHORTNAME/$QL_VARIANT
mkdir -p $MODELS/$SHORTNAME mkdir -p $MODELS/$SHORTNAME
mv java/ql/lib/ext/generated/modelgenerator/$SHORTNAME/$QL_VARIANT $MODELS/$SHORTNAME mv java/ql/lib/ext/generated/$SHORTNAME/$QL_VARIANT $MODELS/$SHORTNAME
cd .. cd ..
} }

View File

@@ -5,7 +5,7 @@ on:
paths: paths:
- "misc/bazel/**" - "misc/bazel/**"
- "misc/codegen/**" - "misc/codegen/**"
- "misc/scripts/models-as-data/*.py" - "misc/scripts/models-as-data/bulk_generate_mad.py"
- "*.bazel*" - "*.bazel*"
- .github/workflows/codegen.yml - .github/workflows/codegen.yml
- .pre-commit-config.yaml - .pre-commit-config.yaml

442
Cargo.lock generated
View File

@@ -140,26 +140,6 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bindgen"
version = "0.72.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
dependencies = [
"bitflags 2.9.4",
"cexpr",
"clang-sys",
"itertools 0.12.1",
"log 0.4.28",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash 2.1.1",
"shlex",
"syn",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@@ -260,9 +240,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.61" version = "1.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" checksum = "65193589c6404eb80b450d618eaf9a2cafaaafd57ecce47370519ef674a7bd44"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"jobserver", "jobserver",
@@ -270,15 +250,6 @@ dependencies = [
"shlex", "shlex",
] ]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.3" version = "1.0.3"
@@ -357,7 +328,7 @@ dependencies = [
"chalk-derive 0.103.0", "chalk-derive 0.103.0",
"chalk-ir 0.103.0", "chalk-ir 0.103.0",
"ena", "ena",
"indexmap 2.14.0", "indexmap 2.11.4",
"itertools 0.12.1", "itertools 0.12.1",
"petgraph", "petgraph",
"rustc-hash 1.1.0", "rustc-hash 1.1.0",
@@ -378,17 +349,6 @@ dependencies = [
"windows-link 0.2.0", "windows-link 0.2.0",
] ]
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.48" version = "4.5.48"
@@ -456,7 +416,6 @@ dependencies = [
"tree-sitter", "tree-sitter",
"tree-sitter-json", "tree-sitter-json",
"tree-sitter-ql", "tree-sitter-ql",
"yeast",
"zstd", "zstd",
] ]
@@ -478,25 +437,6 @@ dependencies = [
"tree-sitter-ruby", "tree-sitter-ruby",
] ]
[[package]]
name = "codeql-extractor-unified"
version = "0.1.0"
dependencies = [
"clap",
"codeql-extractor",
"encoding",
"lazy_static",
"rayon",
"regex",
"serde_json",
"tracing",
"tracing-subscriber",
"tree-sitter",
"tree-sitter-embedded-template",
"tree-sitter-swift",
"yeast",
]
[[package]] [[package]]
name = "codeql-rust" name = "codeql-rust"
version = "0.1.0" version = "0.1.0"
@@ -545,15 +485,6 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
name = "convert_case"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f"
dependencies = [
"unicode-segmentation",
]
[[package]] [[package]]
name = "core-foundation-sys" name = "core-foundation-sys"
version = "0.8.7" version = "0.8.7"
@@ -807,12 +738,6 @@ dependencies = [
"typeid", "typeid",
] ]
[[package]]
name = "fastrand"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
[[package]] [[package]]
name = "figment" name = "figment"
version = "0.10.19" version = "0.10.19"
@@ -829,9 +754,9 @@ dependencies = [
[[package]] [[package]]
name = "find-msvc-tools" name = "find-msvc-tools"
version = "0.1.9" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d"
[[package]] [[package]]
name = "fixedbitset" name = "fixedbitset"
@@ -861,12 +786,6 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "foldhash"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
[[package]] [[package]]
name = "form_urlencoded" name = "form_urlencoded"
version = "1.2.2" version = "1.2.2"
@@ -951,26 +870,9 @@ checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [ dependencies = [
"allocator-api2", "allocator-api2",
"equivalent", "equivalent",
"foldhash 0.1.5", "foldhash",
] ]
[[package]]
name = "hashbrown"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
dependencies = [
"allocator-api2",
"equivalent",
"foldhash 0.2.0",
]
[[package]]
name = "hashbrown"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]] [[package]]
name = "hashlink" name = "hashlink"
version = "0.10.0" version = "0.10.0"
@@ -1157,25 +1059,16 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.14.0" version = "2.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown 0.17.1", "hashbrown 0.15.5",
"serde", "serde",
"serde_core", "serde_core",
] ]
[[package]]
name = "indoc"
version = "2.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
dependencies = [
"rustversion",
]
[[package]] [[package]]
name = "inlinable_string" name = "inlinable_string"
version = "0.1.15" version = "0.1.15"
@@ -1305,16 +1198,6 @@ version = "0.2.175"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
[[package]]
name = "libloading"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
dependencies = [
"cfg-if",
"windows-link 0.2.0",
]
[[package]] [[package]]
name = "line-index" name = "line-index"
version = "0.1.2" version = "0.1.2"
@@ -1380,12 +1263,6 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.8.9" version = "0.8.9"
@@ -1432,16 +1309,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]] [[package]]
name = "notify" name = "notify"
version = "8.2.0" version = "8.2.0"
@@ -1569,12 +1436,6 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "pathdiff"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
[[package]] [[package]]
name = "pear" name = "pear"
version = "0.2.9" version = "0.2.9"
@@ -1630,36 +1491,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
dependencies = [ dependencies = [
"fixedbitset", "fixedbitset",
"indexmap 2.14.0", "indexmap 2.11.4",
]
[[package]]
name = "phf"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf"
dependencies = [
"phf_shared",
"serde",
]
[[package]]
name = "phf_generator"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737"
dependencies = [
"fastrand",
"phf_shared",
]
[[package]]
name = "phf_shared"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266"
dependencies = [
"siphasher",
] ]
[[package]] [[package]]
@@ -1704,25 +1536,6 @@ dependencies = [
"zerocopy", "zerocopy",
] ]
[[package]]
name = "prettyplease"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro-crate"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f"
dependencies = [
"toml_edit 0.25.11+spec-1.1.0",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.101" version = "1.0.101"
@@ -1854,7 +1667,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e876bb2c3e52a8d4e6684526a2d4e81f9d028b939ee4dc5dc775fe10deb44d59" checksum = "e876bb2c3e52a8d4e6684526a2d4e81f9d028b939ee4dc5dc775fe10deb44d59"
dependencies = [ dependencies = [
"dashmap", "dashmap",
"indexmap 2.14.0", "indexmap 2.11.4",
"la-arena", "la-arena",
"ra_ap_cfg", "ra_ap_cfg",
"ra_ap_intern", "ra_ap_intern",
@@ -1896,7 +1709,7 @@ checksum = "ebffdc134eccabc17209d7760cfff7fd12ed18ab6e21188c5e084b97aa38504c"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"either", "either",
"indexmap 2.14.0", "indexmap 2.11.4",
"itertools 0.14.0", "itertools 0.14.0",
"ra_ap_base_db", "ra_ap_base_db",
"ra_ap_cfg", "ra_ap_cfg",
@@ -1926,7 +1739,7 @@ dependencies = [
"drop_bomb", "drop_bomb",
"either", "either",
"fst", "fst",
"indexmap 2.14.0", "indexmap 2.11.4",
"itertools 0.14.0", "itertools 0.14.0",
"la-arena", "la-arena",
"ra-ap-rustc_abi", "ra-ap-rustc_abi",
@@ -1995,7 +1808,7 @@ dependencies = [
"cov-mark", "cov-mark",
"either", "either",
"ena", "ena",
"indexmap 2.14.0", "indexmap 2.11.4",
"itertools 0.14.0", "itertools 0.14.0",
"la-arena", "la-arena",
"oorandom", "oorandom",
@@ -2033,7 +1846,7 @@ dependencies = [
"crossbeam-channel", "crossbeam-channel",
"either", "either",
"fst", "fst",
"indexmap 2.14.0", "indexmap 2.11.4",
"itertools 0.14.0", "itertools 0.14.0",
"line-index", "line-index",
"memchr", "memchr",
@@ -2135,7 +1948,7 @@ version = "0.0.301"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45db9e2df587d56f0738afa89fb2c100ff7c1e9cbe49e07f6a8b62342832211b" checksum = "45db9e2df587d56f0738afa89fb2c100ff7c1e9cbe49e07f6a8b62342832211b"
dependencies = [ dependencies = [
"indexmap 2.14.0", "indexmap 2.11.4",
"ra_ap_intern", "ra_ap_intern",
"ra_ap_paths", "ra_ap_paths",
"ra_ap_span", "ra_ap_span",
@@ -2294,7 +2107,7 @@ checksum = "6c174d6b9b7a7f54687df7e00c3e75ed6f082a7943a9afb1d54f33c0c12773de"
dependencies = [ dependencies = [
"crossbeam-channel", "crossbeam-channel",
"fst", "fst",
"indexmap 2.14.0", "indexmap 2.11.4",
"nohash-hasher", "nohash-hasher",
"ra_ap_paths", "ra_ap_paths",
"ra_ap_stdx", "ra_ap_stdx",
@@ -2426,15 +2239,6 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
[[package]]
name = "relative-path"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bca40a312222d8ba74837cb474edef44b37f561da5f773981007a10bbaa992b0"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "rowan" name = "rowan"
version = "0.15.15" version = "0.15.15"
@@ -2448,57 +2252,6 @@ dependencies = [
"text-size", "text-size",
] ]
[[package]]
name = "rquickjs"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a135375fbac5ba723bb6a48f432a72f81539cedde422f0121a86c7c4e96d8e0d"
dependencies = [
"rquickjs-core",
"rquickjs-macro",
]
[[package]]
name = "rquickjs-core"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bccb7121a123865c8ace4dea42e7ed84d78b90cbaf4ca32c59849d8d210c9672"
dependencies = [
"hashbrown 0.16.1",
"phf",
"relative-path",
"rquickjs-sys",
]
[[package]]
name = "rquickjs-macro"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89f93602cc3112c7f30bf5f29e722784232138692c7df4c52ebbac7e035d900d"
dependencies = [
"convert_case",
"fnv",
"ident_case",
"indexmap 2.14.0",
"phf_generator",
"phf_shared",
"proc-macro-crate",
"proc-macro2",
"quote",
"rquickjs-core",
"syn",
]
[[package]]
name = "rquickjs-sys"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57b1b6528590d4d65dc86b5159eae2d0219709546644c66408b2441696d1d725"
dependencies = [
"bindgen",
"cc",
]
[[package]] [[package]]
name = "rust-extractor-macros" name = "rust-extractor-macros"
version = "0.1.0" version = "0.1.0"
@@ -2564,7 +2317,7 @@ dependencies = [
"crossbeam-utils", "crossbeam-utils",
"hashbrown 0.15.5", "hashbrown 0.15.5",
"hashlink", "hashlink",
"indexmap 2.14.0", "indexmap 2.11.4",
"intrusive-collections", "intrusive-collections",
"papaya", "papaya",
"parking_lot", "parking_lot",
@@ -2653,12 +2406,11 @@ dependencies = [
[[package]] [[package]]
name = "semver" name = "semver"
version = "1.0.28" version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
dependencies = [ dependencies = [
"serde", "serde",
"serde_core",
] ]
[[package]] [[package]]
@@ -2718,7 +2470,7 @@ version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
dependencies = [ dependencies = [
"indexmap 2.14.0", "indexmap 2.11.4",
"itoa", "itoa",
"memchr", "memchr",
"ryu", "ryu",
@@ -2754,7 +2506,7 @@ dependencies = [
"chrono", "chrono",
"hex", "hex",
"indexmap 1.9.3", "indexmap 1.9.3",
"indexmap 2.14.0", "indexmap 2.11.4",
"schemars 0.9.0", "schemars 0.9.0",
"schemars 1.0.4", "schemars 1.0.4",
"serde", "serde",
@@ -2782,7 +2534,7 @@ version = "0.9.34+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
dependencies = [ dependencies = [
"indexmap 2.14.0", "indexmap 2.11.4",
"itoa", "itoa",
"ryu", "ryu",
"serde", "serde",
@@ -2804,18 +2556,6 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "siphasher"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
[[package]]
name = "smallbitvec"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b0e903ee191d8f7a8fbf0d712c3a1699d19e04ceba5ad1eb673053c7d938a09"
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.15.1" version = "1.15.1"
@@ -2892,18 +2632,18 @@ checksum = "144f754d318415ac792f9d69fc87abbbfc043ce2ef041c60f16ad828f638717d"
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "2.0.18" version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "2.0.18" version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -2968,7 +2708,7 @@ dependencies = [
"serde", "serde",
"serde_spanned 0.6.9", "serde_spanned 0.6.9",
"toml_datetime 0.6.11", "toml_datetime 0.6.11",
"toml_edit 0.22.27", "toml_edit",
] ]
[[package]] [[package]]
@@ -2977,13 +2717,13 @@ version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0" checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0"
dependencies = [ dependencies = [
"indexmap 2.14.0", "indexmap 2.11.4",
"serde_core", "serde_core",
"serde_spanned 1.0.2", "serde_spanned 1.0.2",
"toml_datetime 0.7.2", "toml_datetime 0.7.2",
"toml_parser", "toml_parser",
"toml_writer", "toml_writer",
"winnow 0.7.13", "winnow",
] ]
[[package]] [[package]]
@@ -3004,48 +2744,27 @@ dependencies = [
"serde_core", "serde_core",
] ]
[[package]]
name = "toml_datetime"
version = "1.1.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
dependencies = [
"serde_core",
]
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.22.27" version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [ dependencies = [
"indexmap 2.14.0", "indexmap 2.11.4",
"serde", "serde",
"serde_spanned 0.6.9", "serde_spanned 0.6.9",
"toml_datetime 0.6.11", "toml_datetime 0.6.11",
"toml_write", "toml_write",
"winnow 0.7.13", "winnow",
]
[[package]]
name = "toml_edit"
version = "0.25.11+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b"
dependencies = [
"indexmap 2.14.0",
"toml_datetime 1.1.1+spec-1.1.0",
"toml_parser",
"winnow 1.0.2",
] ]
[[package]] [[package]]
name = "toml_parser" name = "toml_parser"
version = "1.1.2+spec-1.1.0" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627"
dependencies = [ dependencies = [
"winnow 1.0.2", "winnow",
] ]
[[package]] [[package]]
@@ -3060,12 +2779,6 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109" checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109"
[[package]]
name = "topological-sort"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
[[package]] [[package]]
name = "tracing" name = "tracing"
version = "0.1.41" version = "0.1.41"
@@ -3140,9 +2853,9 @@ dependencies = [
[[package]] [[package]]
name = "tree-sitter" name = "tree-sitter"
version = "0.26.8" version = "0.25.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "887bd495d0582c5e3e0d8ece2233666169fa56a9644d172fc22ad179ab2d0538" checksum = "ccd2a058a86cfece0bf96f7cce1021efef9c8ed0e892ab74639173e5ed7a34fa"
dependencies = [ dependencies = [
"cc", "cc",
"regex", "regex",
@@ -3162,30 +2875,6 @@ dependencies = [
"tree-sitter-language", "tree-sitter-language",
] ]
[[package]]
name = "tree-sitter-generate"
version = "0.26.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fb2e1bdb1d5f9d23cd5fa68cf98b3bedbd223c92a2edd60bbcf30bcf7180a5"
dependencies = [
"bitflags 2.9.4",
"dunce",
"indexmap 2.14.0",
"indoc",
"log 0.4.28",
"pathdiff",
"regex",
"regex-syntax",
"rquickjs",
"rustc-hash 2.1.1",
"semver",
"serde",
"serde_json",
"smallbitvec",
"thiserror",
"topological-sort",
]
[[package]] [[package]]
name = "tree-sitter-json" name = "tree-sitter-json"
version = "0.24.8" version = "0.24.8"
@@ -3202,16 +2891,6 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4013970217383f67b18aef68f6fb2e8d409bc5755227092d32efb0422ba24b8" checksum = "c4013970217383f67b18aef68f6fb2e8d409bc5755227092d32efb0422ba24b8"
[[package]]
name = "tree-sitter-python"
version = "0.23.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d065aaa27f3aaceaf60c1f0e0ac09e1cb9eb8ed28e7bcdaa52129cffc7f4b04"
dependencies = [
"cc",
"tree-sitter-language",
]
[[package]] [[package]]
name = "tree-sitter-ql" name = "tree-sitter-ql"
version = "0.23.1" version = "0.23.1"
@@ -3232,15 +2911,6 @@ dependencies = [
"tree-sitter-language", "tree-sitter-language",
] ]
[[package]]
name = "tree-sitter-swift"
version = "0.7.2"
dependencies = [
"cc",
"tree-sitter-generate",
"tree-sitter-language",
]
[[package]] [[package]]
name = "triomphe" name = "triomphe"
version = "0.1.14" version = "0.1.14"
@@ -3290,12 +2960,6 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
[[package]]
name = "unicode-segmentation"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.6" version = "0.2.6"
@@ -3685,15 +3349,6 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "winnow"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "wit-bindgen" name = "wit-bindgen"
version = "0.45.1" version = "0.45.1"
@@ -3712,29 +3367,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]]
name = "yeast"
version = "0.1.0"
dependencies = [
"clap",
"serde",
"serde_json",
"serde_yaml",
"tree-sitter",
"tree-sitter-python",
"tree-sitter-ruby",
"yeast-macros",
]
[[package]]
name = "yeast-macros"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "yoke" name = "yoke"
version = "0.8.0" version = "0.8.0"

View File

@@ -4,11 +4,7 @@
resolver = "2" resolver = "2"
members = [ members = [
"shared/tree-sitter-extractor", "shared/tree-sitter-extractor",
"shared/yeast",
"shared/yeast-macros",
"ruby/extractor", "ruby/extractor",
"unified/extractor",
"unified/extractor/tree-sitter-swift",
"rust/extractor", "rust/extractor",
"rust/extractor/macros", "rust/extractor/macros",
"rust/ast-generator", "rust/ast-generator",

View File

@@ -102,7 +102,6 @@ use_repo(
tree_sitter_extractors_deps, tree_sitter_extractors_deps,
"vendor_ts__anyhow-1.0.100", "vendor_ts__anyhow-1.0.100",
"vendor_ts__argfile-0.2.1", "vendor_ts__argfile-0.2.1",
"vendor_ts__cc-1.2.61",
"vendor_ts__chalk-ir-0.104.0", "vendor_ts__chalk-ir-0.104.0",
"vendor_ts__chrono-0.4.42", "vendor_ts__chrono-0.4.42",
"vendor_ts__clap-4.5.48", "vendor_ts__clap-4.5.48",
@@ -142,18 +141,14 @@ use_repo(
"vendor_ts__serde-1.0.228", "vendor_ts__serde-1.0.228",
"vendor_ts__serde_json-1.0.145", "vendor_ts__serde_json-1.0.145",
"vendor_ts__serde_with-3.14.1", "vendor_ts__serde_with-3.14.1",
"vendor_ts__serde_yaml-0.9.34-deprecated",
"vendor_ts__syn-2.0.106", "vendor_ts__syn-2.0.106",
"vendor_ts__toml-0.9.7", "vendor_ts__toml-0.9.7",
"vendor_ts__tracing-0.1.41", "vendor_ts__tracing-0.1.41",
"vendor_ts__tracing-flame-0.2.0", "vendor_ts__tracing-flame-0.2.0",
"vendor_ts__tracing-subscriber-0.3.20", "vendor_ts__tracing-subscriber-0.3.20",
"vendor_ts__tree-sitter-0.26.8", "vendor_ts__tree-sitter-0.25.9",
"vendor_ts__tree-sitter-embedded-template-0.25.0", "vendor_ts__tree-sitter-embedded-template-0.25.0",
"vendor_ts__tree-sitter-generate-0.26.8",
"vendor_ts__tree-sitter-json-0.24.8", "vendor_ts__tree-sitter-json-0.24.8",
"vendor_ts__tree-sitter-language-0.1.5",
"vendor_ts__tree-sitter-python-0.23.6",
"vendor_ts__tree-sitter-ql-0.23.1", "vendor_ts__tree-sitter-ql-0.23.1",
"vendor_ts__tree-sitter-ruby-0.23.1", "vendor_ts__tree-sitter-ruby-0.23.1",
"vendor_ts__triomphe-0.1.14", "vendor_ts__triomphe-0.1.14",
@@ -273,7 +268,7 @@ use_repo(
) )
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk") 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 = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//go/extractor:go.mod") go_deps.from_file(go_mod = "//go/extractor:go.mod")

View File

@@ -8,5 +8,5 @@
import actions import actions
from UsesStep uses from UsesStep uses
where uses.getVersion().regexpMatch("^[A-Fa-f0-9]{40}([A-Fa-f0-9]{24})?$") where uses.getVersion().regexpMatch("^[A-Fa-f0-9]{40}$")
select uses, "This 'uses' step has a pinned SHA version." select uses, "This 'uses' step has a pinned SHA version."

View File

@@ -1,19 +1,3 @@
## 0.4.37
### Minor Analysis Improvements
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, include regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a sha1 or sha256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
## 0.4.36
### Minor Analysis Improvements
* Altered 2 patterns in the `poisonable_steps` modelling. Extra sinks are detected in the following cases: scripts executed via python modules and `go run` in directories are detected as potential mechanisms of injection. For the go execution pattern, the pattern is updated to now ignore flags that occur between go and the specific command. This change may lead to more results being detected by the following queries: `actions/untrusted-checkout/high`, `actions/untrusted-checkout/critical`, `actions/untrusted-checkout-toctou/high`, `actions/untrusted-checkout-toctou/critical`, `actions/cache-poisoning/poisonable-step`, `actions/cache-poisoning/direct-cache` and `actions/artifact-poisoning/path-traversal`.
## 0.4.35
No user-facing changes.
## 0.4.34 ## 0.4.34
### Minor Analysis Improvements ### Minor Analysis Improvements

View File

@@ -1,3 +0,0 @@
## 0.4.35
No user-facing changes.

View File

@@ -1,5 +0,0 @@
## 0.4.36
### Minor Analysis Improvements
* Altered 2 patterns in the `poisonable_steps` modelling. Extra sinks are detected in the following cases: scripts executed via python modules and `go run` in directories are detected as potential mechanisms of injection. For the go execution pattern, the pattern is updated to now ignore flags that occur between go and the specific command. This change may lead to more results being detected by the following queries: `actions/untrusted-checkout/high`, `actions/untrusted-checkout/critical`, `actions/untrusted-checkout-toctou/high`, `actions/untrusted-checkout-toctou/critical`, `actions/cache-poisoning/poisonable-step`, `actions/cache-poisoning/direct-cache` and `actions/artifact-poisoning/path-traversal`.

View File

@@ -1,5 +0,0 @@
## 0.4.37
### Minor Analysis Improvements
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, include regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a sha1 or sha256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.4.37 lastReleaseVersion: 0.4.34

View File

@@ -785,22 +785,7 @@ module Bash {
/** /**
* Holds if the given regex is used to match an alphanumeric string * Holds if the given regex is used to match an alphanumeric string
* eg: `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$`, `^[0-9]+$` or `^[a-zA-Z0-9_]+$` * eg: `^[0-9a-zA-Z]{40}$`, `^[0-9]+$` or `^[a-zA-Z0-9_]+$`
*/ */
string alphaNumericRegex() { string alphaNumericRegex() { result = "^\\^\\[([09azAZ_-]+)\\](\\+|\\{\\d+\\})\\$$" }
exists(string r1, string r2, string r3, string r4 |
// An alphanumeric character class
r1 = "\\[([09azAZ_-]+)\\]" and
// The same as above, followed by a quantifier like `+` or `{20}`
r2 = r1 + "(\\+|\\{\\d+\\})" and
// The same as above, possibly with parentheses around it
r3 = "\\(?" + r2 + "\\)?" and
// The same as above, possibly with a `?` after it
r4 = r3 + "\\??"
|
// The same as above, repeated one or more times, and with `^` at the
// beginning and `$` at the end
result = "^\\^(" + r4 + ")+\\$$"
)
}
} }

View File

@@ -70,7 +70,7 @@ extensions:
- ["(source|sh|bash|zsh|fish)\\s+([^\\s]+)\\b", 2] - ["(source|sh|bash|zsh|fish)\\s+([^\\s]+)\\b", 2]
- ["(node)\\s+([^\\s]+)(\\.js|\\.ts)\\b", 2] - ["(node)\\s+([^\\s]+)(\\.js|\\.ts)\\b", 2]
- ["(python[\\d\\.]*)\\s+([^\\s]+)\\.py\\b", 2] - ["(python[\\d\\.]*)\\s+([^\\s]+)\\.py\\b", 2]
- ["(python[\\d\\.]*)\\s+-m\\s+([A-Za-z_][\\w\\.]*)\\b", 2] # eg: pythonX -m anything(dir or file)
- ["(ruby)\\s+([^\\s]+)\\.rb\\b", 2] - ["(ruby)\\s+([^\\s]+)\\.rb\\b", 2]
- ["(go)\\s+(generate|run)(?:\\s+-[^\\s]+)*\\s+([^\\s]+)", 3] - ["(go)\\s+(generate|run)\\s+([^\\s]+)\\.go\\b", 3]
- ["(dotnet)\\s+([^\\s]+)\\.csproj\\b", 2] - ["(dotnet)\\s+([^\\s]+)\\.csproj\\b", 2]

View File

@@ -1,5 +1,5 @@
name: codeql/actions-all name: codeql/actions-all
version: 0.4.38-dev version: 0.4.35-dev
library: true library: true
warnOnImplicitThis: true warnOnImplicitThis: true
dependencies: dependencies:

View File

@@ -1,40 +1,3 @@
## 0.6.29
### Query Metadata Changes
* Reversed adjustment of the name of `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 `actions/untrusted-checkout/high` and `actions/untrusted-checkout/medium`.
### Major Analysis Improvements
* Adjusted `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
* Altered the alert message for clarity for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`.
* The `actions/unpinned-tag` query now recognizes 64-character SHA-256 commit hashes as properly pinned references, in addition to 40-character SHA-1 hashes.
### Bug Fixes
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on in minor point, added one more listed resource and added one more recommendation for things to check.
## 0.6.28
### Query Metadata Changes
* Adjusted the name of `actions/untrusted-checkout/high` to more clearly describe which parts of the scenario are in a privileged context.
### Minor Analysis Improvements
* The `actions/unpinned-tag` query now analyzes composite action metadata (`action.yml`/`action.yaml` files) in addition to workflow files, providing more comprehensive detection of unpinned action references across the entire Actions ecosystem.
### Bug Fixes
* Fixed help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Previously the messages were unclear as to why and how the vulnerabilities could occur.
## 0.6.27
No user-facing changes.
## 0.6.26 ## 0.6.26
### Major Analysis Improvements ### Major Analysis Improvements

View File

@@ -1,5 +1,5 @@
/** /**
* @name Unpinned tag for a non-immutable Action in workflow or composite action * @name Unpinned tag for a non-immutable Action in workflow
* @description Using a tag for a non-immutable Action that is not pinned to a commit can lead to executing an untrusted Action through a supply chain attack. * @description Using a tag for a non-immutable Action that is not pinned to a commit can lead to executing an untrusted Action through a supply chain attack.
* @kind problem * @kind problem
* @security-severity 5.0 * @security-severity 5.0
@@ -15,9 +15,7 @@ import actions
import codeql.actions.security.UseOfUnversionedImmutableAction import codeql.actions.security.UseOfUnversionedImmutableAction
bindingset[version] bindingset[version]
private predicate isPinnedCommit(string version) { private predicate isPinnedCommit(string version) { version.regexpMatch("^[A-Fa-f0-9]{40}$") }
version.regexpMatch("^[A-Fa-f0-9]{40}([A-Fa-f0-9]{24})?$")
}
bindingset[nwo] bindingset[nwo]
private predicate isTrustedOwner(string nwo) { private predicate isTrustedOwner(string nwo) {
@@ -33,26 +31,15 @@ private predicate isPinnedContainer(string version) {
bindingset[nwo] bindingset[nwo]
private predicate isContainerImage(string nwo) { nwo.regexpMatch("^docker://.+") } private predicate isContainerImage(string nwo) { nwo.regexpMatch("^docker://.+") }
private predicate getStepContainerName(UsesStep uses, string name) { from UsesStep uses, string nwo, string version, Workflow workflow, string name
exists(Workflow workflow |
uses.getEnclosingWorkflow() = workflow and
(
workflow.getName() = name
or
not exists(workflow.getName()) and workflow.getLocation().getFile().getBaseName() = name
)
)
or
exists(CompositeAction action |
uses.getEnclosingCompositeAction() = action and
name = action.getLocation().getFile().getBaseName()
)
}
from UsesStep uses, string nwo, string version, string name
where where
uses.getCallee() = nwo and uses.getCallee() = nwo and
getStepContainerName(uses, name) and uses.getEnclosingWorkflow() = workflow and
(
workflow.getName() = name
or
not exists(workflow.getName()) and workflow.getLocation().getFile().getBaseName() = name
) and
uses.getVersion() = version and uses.getVersion() = version and
not isTrustedOwner(nwo) and not isTrustedOwner(nwo) and
not (if isContainerImage(nwo) then isPinnedContainer(version) else isPinnedCommit(version)) and not (if isContainerImage(nwo) then isPinnedContainer(version) else isPinnedCommit(version)) and

View File

@@ -1,35 +1,6 @@
## Overview ## Overview
GitHub workflows can be triggered through various repository events, including incoming pull requests (PRs) or comments on Issues/PRs. Under certain conditions described below, attackers can take over a repository by opening malicious PRs from forks. The attacks can result in malicious code execution causing unauthorized changes to the repository or exfiltration of repository secrets and a compromise of connected systems. GitHub workflows can be triggered through various repository events, including incoming pull requests (PRs) or comments on Issues/PRs. A potentially dangerous misuse of the triggers such as `pull_request_target` or `issue_comment` followed by an explicit checkout of untrusted code (Pull Request HEAD) may lead to repository compromise if untrusted code gets executed (e.g., due to a modified build script) in a privileged job.
## Workflow Security Model
In GitHub Actions, there is a distinction between unprivileged and privileged workflows. For example, a workflow with a `pull_request` trigger is unprivileged while a workflow with `pull_request_target` is privileged.
This is relevant especially for PRs from forks. Normal PRs can only be submitted by people who have write access to a repository, while PRs from forks can be submitted by anyone.
On a PR from a fork, an unprivileged `pull_request` workflow has only limited capabilities but a privileged `pull_request_target` workflow is much more dangerous. A privileged workflow:
* Runs in the context of the base repository
* Has access to organization and repository secrets (e.g., API keys, deployment tokens)
* Has a read/write `GITHUB_TOKEN` by default
* Can access private resources
Certain triggers automatically grant a workflow elevated privileges:
* `pull_request_target` as described above
* `workflow_run`: Triggered when another workflow completes.
* `issue_comment`: Triggered when a comment is made on an issue or PR.
## Attack Details
* A repository has a privileged workflow
* An attacker forks the repository and adds malicious code (e.g., in the build script)
* The attacker opens a PR from the fork, and, if needed, comments on the PR
* The workflow in the base repository checks out the forked code
* The workflow runs the malicious code
Please note that not only build scripts can be malicious code vectors. There is a large number of other possibilities. Some of them are listed in the [LOTP](https://boostsecurityio.github.io/lotp/) catalog.
## Recommendation ## Recommendation
@@ -41,8 +12,6 @@ The best practice is to handle the potentially untrusted pull request via the **
The artifacts downloaded from the first workflow should be considered untrusted and must be verified. The artifacts downloaded from the first workflow should be considered untrusted and must be verified.
Additionally, ensure that least privilege are used both at the workflow level (through event triggers and workflow permissions) and job level (through job permissions).
## Example ## Example
### Incorrect Usage ### Incorrect Usage
@@ -164,6 +133,3 @@ jobs:
## References ## References
- GitHub Security Lab Research: [Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/). - GitHub Security Lab Research: [Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
- Mitigating risks of untrusted checkout: [GitHub Docs](https://docs.github.com/en/enterprise-cloud@latest/actions/reference/security/secure-use#mitigating-the-risks-of-untrusted-code-checkout).
- Securing with least privilege: [Workflow secure use](https://docs.github.com/en/actions/reference/security/secure-use).
- Living Off the Pipeline: [LOTP](https://boostsecurityio.github.io/lotp/).

View File

@@ -51,6 +51,5 @@ where
event.getName() = checkoutTriggers() and event.getName() = checkoutTriggers() and
not exists(ControlCheck check | check.protects(checkout, event, "untrusted-checkout")) and not exists(ControlCheck check | check.protects(checkout, event, "untrusted-checkout")) and
not exists(ControlCheck check | check.protects(poisonable, event, "untrusted-checkout")) not exists(ControlCheck check | check.protects(poisonable, event, "untrusted-checkout"))
select checkout, checkout, poisonable, select poisonable, checkout, poisonable,
"Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@).", "Potential execution of untrusted code on a privileged workflow ($@)", event, event.getName()
event, event.getName()

View File

@@ -1,35 +1,6 @@
## Overview ## Overview
GitHub workflows can be triggered through various repository events, including incoming pull requests (PRs) or comments on Issues/PRs. Under certain conditions described below, attackers can take over a repository by opening malicious PRs from forks. The attacks can result in malicious code execution causing unauthorized changes to the repository or exfiltration of repository secrets and a compromise of connected systems. GitHub workflows can be triggered through various repository events, including incoming pull requests (PRs) or comments on Issues/PRs. A potentially dangerous misuse of the triggers such as `pull_request_target` or `issue_comment` followed by an explicit checkout of untrusted code (Pull Request HEAD) may lead to repository compromise if untrusted code gets executed (e.g., due to a modified build script) in a privileged job.
## Workflow Security Model
In GitHub Actions, there is a distinction between unprivileged and privileged workflows. For example, a workflow with a `pull_request` trigger is unprivileged while a workflow with `pull_request_target` is privileged.
This is relevant especially for PRs from forks. Normal PRs can only be submitted by people who have write access to a repository, while PRs from forks can be submitted by anyone.
On a PR from a fork, an unprivileged `pull_request` workflow has only limited capabilities but a privileged `pull_request_target` workflow is much more dangerous. A privileged workflow:
* Runs in the context of the base repository
* Has access to organization and repository secrets (e.g., API keys, deployment tokens)
* Has a read/write `GITHUB_TOKEN` by default
* Can access private resources
Certain triggers automatically grant a workflow elevated privileges:
* `pull_request_target` as described above
* `workflow_run`: Triggered when another workflow completes.
* `issue_comment`: Triggered when a comment is made on an issue or PR.
## Attack Details
* A repository has a privileged workflow
* An attacker forks the repository and adds malicious code (e.g., in the build script)
* The attacker opens a PR from the fork, and, if needed, comments on the PR
* The workflow in the base repository checks out the forked code
* The workflow runs the malicious code
Please note that not only build scripts can be malicious code vectors. There is a large number of other possibilities. Some of them are listed in the [LOTP](https://boostsecurityio.github.io/lotp/) catalog.
## Recommendation ## Recommendation
@@ -41,8 +12,6 @@ The best practice is to handle the potentially untrusted pull request via the **
The artifacts downloaded from the first workflow should be considered untrusted and must be verified. The artifacts downloaded from the first workflow should be considered untrusted and must be verified.
Additionally, ensure that least privilege are used both at the workflow level (through event triggers and workflow permissions) and job level (through job permissions).
## Example ## Example
### Incorrect Usage ### Incorrect Usage
@@ -164,6 +133,3 @@ jobs:
## References ## References
- GitHub Security Lab Research: [Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/). - GitHub Security Lab Research: [Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
- Mitigating risks of untrusted checkout: [GitHub Docs](https://docs.github.com/en/enterprise-cloud@latest/actions/reference/security/secure-use#mitigating-the-risks-of-untrusted-code-checkout).
- Securing with least privilege: [Workflow secure use](https://docs.github.com/en/actions/reference/security/secure-use).
- Living Off the Pipeline: [LOTP](https://boostsecurityio.github.io/lotp/).

View File

@@ -1,5 +1,5 @@
/** /**
* @name Checkout of untrusted code in a privileged context * @name Checkout of untrusted code in trusted context
* @description Privileged workflows have read/write access to the base repository and access to secrets. * @description Privileged workflows have read/write access to the base repository and access to secrets.
* By explicitly checking out and running the build script from a fork the untrusted code is running in an environment * By explicitly checking out and running the build script from a fork the untrusted code is running in an environment
* that is able to push to the base repository and to access secrets. * that is able to push to the base repository and to access secrets.
@@ -42,6 +42,5 @@ where
not event.getName() = "issue_comment" and not event.getName() = "issue_comment" and
not exists(ControlCheck check | check.protects(checkout, event, "untrusted-checkout")) not exists(ControlCheck check | check.protects(checkout, event, "untrusted-checkout"))
) )
select checkout, select checkout, "Potential execution of untrusted code on a privileged workflow ($@)", event,
"Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@).", event.getName()
event, event.getName()

View File

@@ -1,35 +1,6 @@
## Overview ## Overview
GitHub workflows can be triggered through various repository events, including incoming pull requests (PRs) or comments on Issues/PRs. Under certain conditions described below, attackers can take over a repository by opening malicious PRs from forks. The attacks can result in malicious code execution causing unauthorized changes to the repository or exfiltration of repository secrets and a compromise of connected systems. GitHub workflows can be triggered through various repository events, including incoming pull requests (PRs) or comments on Issues/PRs. A potentially dangerous misuse of the triggers such as `pull_request_target` or `issue_comment` followed by an explicit checkout of untrusted code (Pull Request HEAD) may lead to repository compromise if untrusted code gets executed (e.g., due to a modified build script) in a privileged job.
## Workflow Security Model
In GitHub Actions, there is a distinction between unprivileged and privileged workflows. For example, a workflow with a `pull_request` trigger is unprivileged while a workflow with `pull_request_target` is privileged.
This is relevant especially for PRs from forks. Normal PRs can only be submitted by people who have write access to a repository, while PRs from forks can be submitted by anyone.
On a PR from a fork, an unprivileged `pull_request` workflow has only limited capabilities but a privileged `pull_request_target` workflow is much more dangerous. A privileged workflow:
* Runs in the context of the base repository
* Has access to organization and repository secrets (e.g., API keys, deployment tokens)
* Has a read/write `GITHUB_TOKEN` by default
* Can access private resources
Certain triggers automatically grant a workflow elevated privileges:
* `pull_request_target` as described above
* `workflow_run`: Triggered when another workflow completes.
* `issue_comment`: Triggered when a comment is made on an issue or PR.
## Attack Details
* A repository has a privileged workflow
* An attacker forks the repository and adds malicious code (e.g., in the build script)
* The attacker opens a PR from the fork, and, if needed, comments on the PR
* The workflow in the base repository checks out the forked code
* The workflow runs the malicious code
Please note that not only build scripts can be malicious code vectors. There is a large number of other possibilities. Some of them are listed in the [LOTP](https://boostsecurityio.github.io/lotp/) catalog.
## Recommendation ## Recommendation
@@ -41,8 +12,6 @@ The best practice is to handle the potentially untrusted pull request via the **
The artifacts downloaded from the first workflow should be considered untrusted and must be verified. The artifacts downloaded from the first workflow should be considered untrusted and must be verified.
Additionally, ensure that least privilege are used both at the workflow level (through event triggers and workflow permissions) and job level (through job permissions).
## Example ## Example
### Incorrect Usage ### Incorrect Usage
@@ -164,6 +133,3 @@ jobs:
## References ## References
- GitHub Security Lab Research: [Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/). - GitHub Security Lab Research: [Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
- Mitigating risks of untrusted checkout: [GitHub Docs](https://docs.github.com/en/enterprise-cloud@latest/actions/reference/security/secure-use#mitigating-the-risks-of-untrusted-code-checkout).
- Securing with least privilege: [Workflow secure use](https://docs.github.com/en/actions/reference/security/secure-use).
- Living Off the Pipeline: [LOTP](https://boostsecurityio.github.io/lotp/).

View File

@@ -1,5 +1,5 @@
/** /**
* @name Checkout of untrusted code in a trusted context * @name Checkout of untrusted code in trusted context
* @description Privileged workflows have read/write access to the base repository and access to secrets. * @description Privileged workflows have read/write access to the base repository and access to secrets.
* By explicitly checking out and running the build script from a fork the untrusted code is running in an environment * By explicitly checking out and running the build script from a fork the untrusted code is running in an environment
* that is able to push to the base repository and to access secrets. * that is able to push to the base repository and to access secrets.

View File

@@ -1,3 +0,0 @@
## 0.6.27
No user-facing changes.

View File

@@ -1,13 +0,0 @@
## 0.6.28
### Query Metadata Changes
* Adjusted the name of `actions/untrusted-checkout/high` to more clearly describe which parts of the scenario are in a privileged context.
### Minor Analysis Improvements
* The `actions/unpinned-tag` query now analyzes composite action metadata (`action.yml`/`action.yaml` files) in addition to workflow files, providing more comprehensive detection of unpinned action references across the entire Actions ecosystem.
### Bug Fixes
* Fixed help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Previously the messages were unclear as to why and how the vulnerabilities could occur.

View File

@@ -1,18 +0,0 @@
## 0.6.29
### Query Metadata Changes
* Reversed adjustment of the name of `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 `actions/untrusted-checkout/high` and `actions/untrusted-checkout/medium`.
### Major Analysis Improvements
* Adjusted `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
* Altered the alert message for clarity for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`.
* The `actions/unpinned-tag` query now recognizes 64-character SHA-256 commit hashes as properly pinned references, in addition to 40-character SHA-1 hashes.
### Bug Fixes
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on in minor point, added one more listed resource and added one more recommendation for things to check.

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.6.29 lastReleaseVersion: 0.6.26

View File

@@ -1,5 +1,5 @@
name: codeql/actions-queries name: codeql/actions-queries
version: 0.6.30-dev version: 0.6.27-dev
library: false library: false
warnOnImplicitThis: true warnOnImplicitThis: true
groups: [actions, queries] groups: [actions, queries]

View File

@@ -1,6 +0,0 @@
name: Composite unpinned tag test
runs:
using: "composite"
steps:
- uses: foo/bar@v2
- uses: foo/bar@25b062c917b0c75f8b47d8469aff6c94ffd89abb

View File

@@ -11,9 +11,3 @@ jobs:
- uses: foo/bar@25b062c917b0c75f8b47d8469aff6c94ffd89abb - uses: foo/bar@25b062c917b0c75f8b47d8469aff6c94ffd89abb
- uses: docker://foo/bar@latest - uses: docker://foo/bar@latest
- uses: docker://foo/bar@sha256:887a259a5a534f3c4f36cb02dca341673c6089431057242cdc931e9f133147e9 - uses: docker://foo/bar@sha256:887a259a5a534f3c4f36cb02dca341673c6089431057242cdc931e9f133147e9
# SHA-256 pinned (64 hex chars) - should NOT be flagged
- uses: foo/bar@25b062c917b0c75f8b47d8469aff6c94ffd89abb25b062c917b0c75f8b47d84d
# SHA-1 pinned (40 hex chars) regression - should NOT be flagged
- uses: foo/bar@a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
# Invalid 50-char hex string - should be flagged
- uses: foo/bar@a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2a1b2c3d4e5

View File

@@ -1,4 +1,3 @@
| .github/actions/unpinned-tag/action.yml:5:13:5:22 | foo/bar@v2 | Unpinned 3rd party Action 'action.yml' step $@ uses 'foo/bar' with ref 'v2', not a pinned commit hash | .github/actions/unpinned-tag/action.yml:5:7:6:4 | Uses Step | Uses Step |
| .github/workflows/actor_trusted_checkout.yml:19:13:19:36 | completely/fakeaction@v2 | Unpinned 3rd party Action 'actor_trusted_checkout.yml' step $@ uses 'completely/fakeaction' with ref 'v2', not a pinned commit hash | .github/workflows/actor_trusted_checkout.yml:19:7:23:4 | Uses Step | Uses Step | | .github/workflows/actor_trusted_checkout.yml:19:13:19:36 | completely/fakeaction@v2 | Unpinned 3rd party Action 'actor_trusted_checkout.yml' step $@ uses 'completely/fakeaction' with ref 'v2', not a pinned commit hash | .github/workflows/actor_trusted_checkout.yml:19:7:23:4 | Uses Step | Uses Step |
| .github/workflows/actor_trusted_checkout.yml:23:13:23:37 | fakerepo/comment-on-pr@v1 | Unpinned 3rd party Action 'actor_trusted_checkout.yml' step $@ uses 'fakerepo/comment-on-pr' with ref 'v1', not a pinned commit hash | .github/workflows/actor_trusted_checkout.yml:23:7:26:21 | Uses Step | Uses Step | | .github/workflows/actor_trusted_checkout.yml:23:13:23:37 | fakerepo/comment-on-pr@v1 | Unpinned 3rd party Action 'actor_trusted_checkout.yml' step $@ uses 'fakerepo/comment-on-pr' with ref 'v1', not a pinned commit hash | .github/workflows/actor_trusted_checkout.yml:23:7:26:21 | Uses Step | Uses Step |
| .github/workflows/artifactpoisoning21.yml:13:15:13:49 | dawidd6/action-download-artifact@v2 | Unpinned 3rd party Action 'Pull Request Open' step $@ uses 'dawidd6/action-download-artifact' with ref 'v2', not a pinned commit hash | .github/workflows/artifactpoisoning21.yml:13:9:18:6 | Uses Step | Uses Step | | .github/workflows/artifactpoisoning21.yml:13:15:13:49 | dawidd6/action-download-artifact@v2 | Unpinned 3rd party Action 'Pull Request Open' step $@ uses 'dawidd6/action-download-artifact' with ref 'v2', not a pinned commit hash | .github/workflows/artifactpoisoning21.yml:13:9:18:6 | Uses Step | Uses Step |
@@ -34,4 +33,3 @@
| .github/workflows/test18.yml:37:21:37:63 | sonarsource/sonarcloud-github-action@master | Unpinned 3rd party Action 'Sonar' step $@ uses 'sonarsource/sonarcloud-github-action' with ref 'master', not a pinned commit hash | .github/workflows/test18.yml:36:15:40:58 | Uses Step | Uses Step | | .github/workflows/test18.yml:37:21:37:63 | sonarsource/sonarcloud-github-action@master | Unpinned 3rd party Action 'Sonar' step $@ uses 'sonarsource/sonarcloud-github-action' with ref 'master', not a pinned commit hash | .github/workflows/test18.yml:36:15:40:58 | Uses Step | Uses Step |
| .github/workflows/unpinned_tags.yml:10:13:10:22 | foo/bar@v1 | Unpinned 3rd party Action 'unpinned_tags.yml' step $@ uses 'foo/bar' with ref 'v1', not a pinned commit hash | .github/workflows/unpinned_tags.yml:10:7:11:4 | Uses Step | Uses Step | | .github/workflows/unpinned_tags.yml:10:13:10:22 | foo/bar@v1 | Unpinned 3rd party Action 'unpinned_tags.yml' step $@ uses 'foo/bar' with ref 'v1', not a pinned commit hash | .github/workflows/unpinned_tags.yml:10:7:11:4 | Uses Step | Uses Step |
| .github/workflows/unpinned_tags.yml:12:13:12:35 | docker://foo/bar@latest | Unpinned 3rd party Action 'unpinned_tags.yml' step $@ uses 'docker://foo/bar' with ref 'latest', not a pinned commit hash | .github/workflows/unpinned_tags.yml:12:7:13:4 | Uses Step | Uses Step | | .github/workflows/unpinned_tags.yml:12:13:12:35 | docker://foo/bar@latest | Unpinned 3rd party Action 'unpinned_tags.yml' step $@ uses 'docker://foo/bar' with ref 'latest', not a pinned commit hash | .github/workflows/unpinned_tags.yml:12:7:13:4 | Uses Step | Uses Step |
| .github/workflows/unpinned_tags.yml:19:13:19:70 | foo/bar@a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2a1b2c3d4e5 | Unpinned 3rd party Action 'unpinned_tags.yml' step $@ uses 'foo/bar' with ref 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2a1b2c3d4e5', not a pinned commit hash | .github/workflows/unpinned_tags.yml:19:7:19:71 | Uses Step | Uses Step |

View File

@@ -8,7 +8,6 @@ edges
| .github/actions/download-artifact/action.yaml:25:7:29:4 | Run Step | .github/actions/download-artifact/action.yaml:29:7:32:18 | Run Step | | .github/actions/download-artifact/action.yaml:25:7:29:4 | Run Step | .github/actions/download-artifact/action.yaml:29:7:32:18 | Run Step |
| .github/actions/download-artifact/action.yaml:29:7:32:18 | Run Step | .github/workflows/artifactpoisoning91.yml:19:9:25:6 | Run Step: metadata | | .github/actions/download-artifact/action.yaml:29:7:32:18 | Run Step | .github/workflows/artifactpoisoning91.yml:19:9:25:6 | Run Step: metadata |
| .github/actions/download-artifact/action.yaml:29:7:32:18 | Run Step | .github/workflows/resolve-args.yml:22:9:36:13 | Run Step: resolve-step | | .github/actions/download-artifact/action.yaml:29:7:32:18 | Run Step | .github/workflows/resolve-args.yml:22:9:36:13 | Run Step: resolve-step |
| .github/actions/unpinned-tag/action.yml:5:7:6:4 | Uses Step | .github/actions/unpinned-tag/action.yml:6:7:6:61 | Uses Step |
| .github/workflows/actor_trusted_checkout.yml:9:7:14:4 | Uses Step | .github/workflows/actor_trusted_checkout.yml:14:7:15:4 | Uses Step | | .github/workflows/actor_trusted_checkout.yml:9:7:14:4 | Uses Step | .github/workflows/actor_trusted_checkout.yml:14:7:15:4 | Uses Step |
| .github/workflows/actor_trusted_checkout.yml:14:7:15:4 | Uses Step | .github/workflows/actor_trusted_checkout.yml:15:7:19:4 | Run Step | | .github/workflows/actor_trusted_checkout.yml:14:7:15:4 | Uses Step | .github/workflows/actor_trusted_checkout.yml:15:7:19:4 | Run Step |
| .github/workflows/actor_trusted_checkout.yml:15:7:19:4 | Run Step | .github/workflows/actor_trusted_checkout.yml:19:7:23:4 | Uses Step | | .github/workflows/actor_trusted_checkout.yml:15:7:19:4 | Run Step | .github/workflows/actor_trusted_checkout.yml:19:7:23:4 | Uses Step |
@@ -312,10 +311,7 @@ edges
| .github/workflows/unpinned_tags.yml:9:7:10:4 | Uses Step | .github/workflows/unpinned_tags.yml:10:7:11:4 | Uses Step | | .github/workflows/unpinned_tags.yml:9:7:10:4 | Uses Step | .github/workflows/unpinned_tags.yml:10:7:11:4 | Uses Step |
| .github/workflows/unpinned_tags.yml:10:7:11:4 | Uses Step | .github/workflows/unpinned_tags.yml:11:7:12:4 | Uses Step | | .github/workflows/unpinned_tags.yml:10:7:11:4 | Uses Step | .github/workflows/unpinned_tags.yml:11:7:12:4 | Uses Step |
| .github/workflows/unpinned_tags.yml:11:7:12:4 | Uses Step | .github/workflows/unpinned_tags.yml:12:7:13:4 | Uses Step | | .github/workflows/unpinned_tags.yml:11:7:12:4 | Uses Step | .github/workflows/unpinned_tags.yml:12:7:13:4 | Uses Step |
| .github/workflows/unpinned_tags.yml:12:7:13:4 | Uses Step | .github/workflows/unpinned_tags.yml:13:7:15:4 | Uses Step | | .github/workflows/unpinned_tags.yml:12:7:13:4 | Uses Step | .github/workflows/unpinned_tags.yml:13:7:13:101 | Uses Step |
| .github/workflows/unpinned_tags.yml:13:7:15:4 | Uses Step | .github/workflows/unpinned_tags.yml:15:7:17:4 | Uses Step |
| .github/workflows/unpinned_tags.yml:15:7:17:4 | Uses Step | .github/workflows/unpinned_tags.yml:17:7:19:4 | Uses Step |
| .github/workflows/unpinned_tags.yml:17:7:19:4 | Uses Step | .github/workflows/unpinned_tags.yml:19:7:19:71 | Uses Step |
| .github/workflows/untrusted_checkout2.yml:7:9:14:6 | Run Step: pr_number | .github/workflows/untrusted_checkout2.yml:14:9:19:72 | Run Step | | .github/workflows/untrusted_checkout2.yml:7:9:14:6 | Run Step: pr_number | .github/workflows/untrusted_checkout2.yml:14:9:19:72 | Run Step |
| .github/workflows/untrusted_checkout3.yml:11:9:12:6 | Uses Step | .github/workflows/untrusted_checkout3.yml:12:9:13:6 | Uses Step | | .github/workflows/untrusted_checkout3.yml:11:9:12:6 | Uses Step | .github/workflows/untrusted_checkout3.yml:12:9:13:6 | Uses Step |
| .github/workflows/untrusted_checkout3.yml:12:9:13:6 | Uses Step | .github/actions/dangerous-git-checkout/action.yml:6:7:11:4 | Uses Step | | .github/workflows/untrusted_checkout3.yml:12:9:13:6 | Uses Step | .github/actions/dangerous-git-checkout/action.yml:6:7:11:4 | Uses Step |
@@ -338,42 +334,42 @@ edges
| .github/workflows/workflow_run_untrusted_checkout_2.yml:13:9:16:6 | Uses Step | .github/workflows/workflow_run_untrusted_checkout_2.yml:16:9:18:31 | Uses Step | | .github/workflows/workflow_run_untrusted_checkout_2.yml:13:9:16:6 | Uses Step | .github/workflows/workflow_run_untrusted_checkout_2.yml:16:9:18:31 | Uses Step |
| .github/workflows/workflow_run_untrusted_checkout_3.yml:13:9:16:6 | Uses Step | .github/workflows/workflow_run_untrusted_checkout_3.yml:16:9:18:31 | Uses Step | | .github/workflows/workflow_run_untrusted_checkout_3.yml:13:9:16:6 | Uses Step | .github/workflows/workflow_run_untrusted_checkout_3.yml:16:9:18:31 | Uses Step |
#select #select
| .github/actions/dangerous-git-checkout/action.yml:6:7:11:4 | Uses Step | .github/actions/dangerous-git-checkout/action.yml:6:7:11:4 | Uses Step | .github/workflows/untrusted_checkout3.yml:13:9:13:23 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout3.yml:4:3:4:14 | workflow_run | workflow_run | | .github/workflows/auto_ci.yml:32:9:37:6 | Run Step | .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:32:9:37:6 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:32:9:37:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target | | .github/workflows/auto_ci.yml:48:9:52:2 | Run Step | .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:48:9:52:2 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:48:9:52:2 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target | | .github/workflows/auto_ci.yml:79:9:84:6 | Run Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:79:9:84:6 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:79:9:84:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target | | .github/workflows/auto_ci.yml:84:9:93:6 | Run Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:84:9:93:6 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:84:9:93:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target | | .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/dependabot3.yml:3:5:3:23 | pull_request_target | pull_request_target |
| .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/dependabot3.yml:3:5:3:23 | pull_request_target | pull_request_target | | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/reusable_caller1.yaml:4:3:4:21 | pull_request_target | pull_request_target |
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/reusable_caller1.yaml:4:3:4:21 | pull_request_target | pull_request_target | | .github/workflows/gitcheckout.yml:21:11:23:22 | Run Step | .github/workflows/gitcheckout.yml:10:11:18:8 | Run Step | .github/workflows/gitcheckout.yml:21:11:23:22 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/gitcheckout.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/gitcheckout.yml:10:11:18:8 | Run Step | .github/workflows/gitcheckout.yml:10:11:18:8 | Run Step | .github/workflows/gitcheckout.yml:21:11:23:22 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/gitcheckout.yml:2:3:2:21 | pull_request_target | pull_request_target | | .github/workflows/label_trusted_checkout2.yml:17:7:21:4 | Run Step | .github/workflows/label_trusted_checkout2.yml:12:7:16:4 | Uses Step | .github/workflows/label_trusted_checkout2.yml:17:7:21:4 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/label_trusted_checkout2.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/label_trusted_checkout2.yml:12:7:16:4 | Uses Step | .github/workflows/label_trusted_checkout2.yml:12:7:16:4 | Uses Step | .github/workflows/label_trusted_checkout2.yml:17:7:21:4 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/label_trusted_checkout2.yml:2:3:2:21 | pull_request_target | pull_request_target | | .github/workflows/level0.yml:107:9:112:2 | Run Step | .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:107:9:112:2 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/level0.yml:5:3:5:15 | issue_comment | issue_comment |
| .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:107:9:112:2 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/level0.yml:5:3:5:15 | issue_comment | issue_comment | | .github/workflows/level0.yml:107:9:112:2 | Run Step | .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:107:9:112:2 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/level0.yml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:107:9:112:2 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/level0.yml:7:3:7:21 | pull_request_target | pull_request_target | | .github/workflows/level0.yml:133:9:135:23 | Run Step | .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:133:9:135:23 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/level0.yml:5:3:5:15 | issue_comment | issue_comment |
| .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:133:9:135:23 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/level0.yml:5:3:5:15 | issue_comment | issue_comment | | .github/workflows/level0.yml:133:9:135:23 | Run Step | .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:133:9:135:23 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/level0.yml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:133:9:135:23 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/level0.yml:7:3:7:21 | pull_request_target | pull_request_target | | .github/workflows/poc2.yml:42:9:47:6 | Uses Step | .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:42:9:47:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/poc2.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:42:9:47:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/poc2.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/poc2.yml:52:9:58:24 | Run Step | .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:52:9:58:24 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/poc2.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:52:9:58:24 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/poc2.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/pr-workflow.yml:222:9:227:6 | Uses Step | .github/workflows/pr-workflow.yml:216:9:222:6 | Uses Step | .github/workflows/pr-workflow.yml:222:9:227:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:216:9:222:6 | Uses Step | .github/workflows/pr-workflow.yml:216:9:222:6 | Uses Step | .github/workflows/pr-workflow.yml:222:9:227:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target | | .github/workflows/pr-workflow.yml:256:9:261:6 | Uses Step | .github/workflows/pr-workflow.yml:250:9:256:6 | Uses Step | .github/workflows/pr-workflow.yml:256:9:261:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:250:9:256:6 | Uses Step | .github/workflows/pr-workflow.yml:250:9:256:6 | Uses Step | .github/workflows/pr-workflow.yml:256:9:261:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target | | .github/workflows/pr-workflow.yml:290:9:295:6 | Uses Step | .github/workflows/pr-workflow.yml:284:9:290:6 | Uses Step | .github/workflows/pr-workflow.yml:290:9:295:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:284:9:290:6 | Uses Step | .github/workflows/pr-workflow.yml:284:9:290:6 | Uses Step | .github/workflows/pr-workflow.yml:290:9:295:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target | | .github/workflows/pr-workflow.yml:391:9:395:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:391:9:395:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:391:9:395:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target | | .github/workflows/pr-workflow.yml:395:9:404:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:395:9:404:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:395:9:404:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target | | .github/workflows/pr-workflow.yml:404:9:414:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:404:9:414:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:404:9:414:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target | | .github/workflows/pr-workflow.yml:414:9:423:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:414:9:423:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:414:9:423:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target | | .github/workflows/pr-workflow.yml:423:9:432:2 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:423:9:432:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:423:9:432:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target | | .github/workflows/reusable_local.yml:26:9:29:7 | Run Step | .github/workflows/reusable_local.yml:23:9:26:6 | Uses Step | .github/workflows/reusable_local.yml:26:9:29:7 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/reusable_caller3.yaml:4:3:4:21 | pull_request_target | pull_request_target |
| .github/workflows/reusable_local.yml:23:9:26:6 | Uses Step | .github/workflows/reusable_local.yml:23:9:26:6 | Uses Step | .github/workflows/reusable_local.yml:26:9:29:7 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/reusable_caller3.yaml:4:3:4:21 | pull_request_target | pull_request_target | | .github/workflows/test7.yml:33:9:36:6 | Run Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:33:9:36:6 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:33:9:36:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/test7.yml:36:9:39:6 | Run Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:36:9:39:6 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:36:9:39:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/test7.yml:49:9:59:6 | Run Step: benchmark-pr | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:49:9:59:6 | Run Step: benchmark-pr | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:49:9:59:6 | Run Step: benchmark-pr | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/test7.yml:59:9:60:6 | Run Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:59:9:60:6 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:59:9:60:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/test7.yml:60:9:60:37 | Run Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:60:9:60:37 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:60:9:60:37 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test7.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/test10.yml:25:9:30:2 | Run Step | .github/workflows/test10.yml:20:9:25:6 | Uses Step | .github/workflows/test10.yml:25:9:30:2 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test10.yml:8:3:8:21 | pull_request_target | pull_request_target |
| .github/workflows/test10.yml:20:9:25:6 | Uses Step | .github/workflows/test10.yml:20:9:25:6 | Uses Step | .github/workflows/test10.yml:25:9:30:2 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test10.yml:8:3:8:21 | pull_request_target | pull_request_target | | .github/workflows/test11.yml:90:7:93:54 | Uses Step | .github/workflows/test11.yml:84:7:90:4 | Uses Step | .github/workflows/test11.yml:90:7:93:54 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test11.yml:5:3:5:15 | issue_comment | issue_comment |
| .github/workflows/test11.yml:84:7:90:4 | Uses Step | .github/workflows/test11.yml:84:7:90:4 | Uses Step | .github/workflows/test11.yml:90:7:93:54 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test11.yml:5:3:5:15 | issue_comment | issue_comment | | .github/workflows/test17.yml:19:15:23:58 | Uses Step | .github/workflows/test17.yml:12:15:19:12 | Uses Step | .github/workflows/test17.yml:19:15:23:58 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test17.yml:3:5:3:16 | workflow_run | workflow_run |
| .github/workflows/test17.yml:12:15:19:12 | Uses Step | .github/workflows/test17.yml:12:15:19:12 | Uses Step | .github/workflows/test17.yml:19:15:23:58 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test17.yml:3:5:3:16 | workflow_run | workflow_run | | .github/workflows/test27.yml:21:9:22:16 | Run Step | .github/workflows/test27.yml:18:9:21:6 | Uses Step | .github/workflows/test27.yml:21:9:22:16 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test26.yml:4:3:4:14 | workflow_run | workflow_run |
| .github/workflows/test27.yml:18:9:21:6 | Uses Step | .github/workflows/test27.yml:18:9:21:6 | Uses Step | .github/workflows/test27.yml:21:9:22:16 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test26.yml:4:3:4:14 | workflow_run | workflow_run | | .github/workflows/test29.yml:14:7:21:11 | Uses Step | .github/workflows/test29.yml:8:7:14:4 | Uses Step | .github/workflows/test29.yml:14:7:21:11 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test29.yml:1:5:1:23 | pull_request_target | pull_request_target |
| .github/workflows/test29.yml:8:7:14:4 | Uses Step | .github/workflows/test29.yml:8:7:14:4 | Uses Step | .github/workflows/test29.yml:14:7:21:11 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test29.yml:1:5:1:23 | pull_request_target | pull_request_target | | .github/workflows/untrusted_checkout3.yml:13:9:13:23 | Run Step | .github/actions/dangerous-git-checkout/action.yml:6:7:11:4 | Uses Step | .github/workflows/untrusted_checkout3.yml:13:9:13:23 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout3.yml:4:3:4:14 | workflow_run | workflow_run |
| .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:35:7:41:4 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment | | .github/workflows/untrusted_checkout4.yml:35:7:41:4 | Run Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:35:7:41:4 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment |
| .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:41:7:47:4 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment | | .github/workflows/untrusted_checkout4.yml:41:7:47:4 | Run Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:41:7:47:4 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment |
| .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:47:7:51:46 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment | | .github/workflows/untrusted_checkout4.yml:47:7:51:46 | Run Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:47:7:51:46 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment |
| .github/workflows/untrusted_checkout.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout.yml:15:9:18:2 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | pull_request_target | | .github/workflows/untrusted_checkout.yml:15:9:18:2 | Run Step | .github/workflows/untrusted_checkout.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout.yml:15:9:18:2 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/untrusted_checkout.yml:23:9:26:6 | Uses Step | .github/workflows/untrusted_checkout.yml:23:9:26:6 | Uses Step | .github/workflows/untrusted_checkout.yml:30:9:32:23 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | pull_request_target | | .github/workflows/untrusted_checkout.yml:30:9:32:23 | Run Step | .github/workflows/untrusted_checkout.yml:23:9:26:6 | Uses Step | .github/workflows/untrusted_checkout.yml:30:9:32:23 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | pull_request_target |

View File

@@ -1,23 +1,23 @@
| .github/workflows/issue_comment_direct.yml:12:9:16:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_direct.yml:12:9:16:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_direct.yml:20:9:24:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_direct.yml:20:9:24:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_direct.yml:28:9:32:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_direct.yml:28:9:32:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_direct.yml:35:9:40:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_direct.yml:35:9:40:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_direct.yml:43:9:46:126 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_direct.yml:43:9:46:126 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_direct.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_heuristic.yml:28:9:33:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_heuristic.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_heuristic.yml:28:9:33:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_heuristic.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_heuristic.yml:48:7:50:46 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_heuristic.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_heuristic.yml:48:7:50:46 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_heuristic.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit2.yml:27:9:31:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit2.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_octokit2.yml:27:9:31:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit2.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:26:9:30:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_octokit.yml:26:9:30:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:30:9:35:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_octokit.yml:30:9:35:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:57:9:62:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_octokit.yml:57:9:62:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:79:9:83:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_octokit.yml:79:9:83:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:95:9:100:2 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_octokit.yml:95:9:100:2 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/issue_comment_octokit.yml:109:9:114:66 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment | | .github/workflows/issue_comment_octokit.yml:109:9:114:66 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/issue_comment_octokit.yml:4:3:4:15 | issue_comment | issue_comment |
| .github/workflows/pr-workflow.yml:103:9:109:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target | | .github/workflows/pr-workflow.yml:103:9:109:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:139:9:144:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target | | .github/workflows/pr-workflow.yml:139:9:144:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/pr-workflow.yml:444:9:449:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target | | .github/workflows/pr-workflow.yml:444:9:449:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | pull_request_target |
| .github/workflows/test13.yml:20:7:25:4 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/test13.yml:2:3:2:15 | issue_comment | issue_comment | | .github/workflows/test13.yml:20:7:25:4 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/test13.yml:2:3:2:15 | issue_comment | issue_comment |
| .github/workflows/untrusted_checkout2.yml:14:9:19:72 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout2.yml:1:5:1:17 | issue_comment | issue_comment | | .github/workflows/untrusted_checkout2.yml:14:9:19:72 | Run Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/untrusted_checkout2.yml:1:5:1:17 | issue_comment | issue_comment |
| .github/workflows/workflow_run_untrusted_checkout.yml:13:9:16:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/workflow_run_untrusted_checkout.yml:2:3:2:14 | workflow_run | workflow_run | | .github/workflows/workflow_run_untrusted_checkout.yml:13:9:16:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/workflow_run_untrusted_checkout.yml:2:3:2:14 | workflow_run | workflow_run |
| .github/workflows/workflow_run_untrusted_checkout.yml:16:9:18:31 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/workflow_run_untrusted_checkout.yml:2:3:2:14 | workflow_run | workflow_run | | .github/workflows/workflow_run_untrusted_checkout.yml:16:9:18:31 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/workflow_run_untrusted_checkout.yml:2:3:2:14 | workflow_run | workflow_run |
| .github/workflows/workflow_run_untrusted_checkout_2.yml:13:9:16:6 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/workflow_run_untrusted_checkout_2.yml:2:3:2:14 | workflow_run | workflow_run | | .github/workflows/workflow_run_untrusted_checkout_2.yml:13:9:16:6 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/workflow_run_untrusted_checkout_2.yml:2:3:2:14 | workflow_run | workflow_run |
| .github/workflows/workflow_run_untrusted_checkout_2.yml:16:9:18:31 | Uses Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/workflow_run_untrusted_checkout_2.yml:2:3:2:14 | workflow_run | workflow_run | | .github/workflows/workflow_run_untrusted_checkout_2.yml:16:9:18:31 | Uses Step | Potential execution of untrusted code on a privileged workflow ($@) | .github/workflows/workflow_run_untrusted_checkout_2.yml:2:3:2:14 | workflow_run | workflow_run |

View File

@@ -11,6 +11,10 @@
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll", "java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll" "csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll"
], ],
"Bound Java/C#": [
"java/ql/lib/semmle/code/java/dataflow/Bound.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/Bound.qll"
],
"ModulusAnalysis Java/C#": [ "ModulusAnalysis Java/C#": [
"java/ql/lib/semmle/code/java/dataflow/ModulusAnalysis.qll", "java/ql/lib/semmle/code/java/dataflow/ModulusAnalysis.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/ModulusAnalysis.qll" "csharp/ql/lib/semmle/code/csharp/dataflow/ModulusAnalysis.qll"

View File

@@ -1,2 +0,0 @@
description: Fix NameQualifier inconsistency
compatibility: full

View File

@@ -1,6 +0,0 @@
description: Support alias templates
compatibility: full
is_alias_template.rel: delete
alias_instantiation.rel: delete
alias_template_argument.rel: delete
alias_template_argument_value.rel: delete

View File

@@ -1,6 +0,0 @@
description: Capture information about one template being generated from another
compatibility: full
class_template_generated_from.rel: delete
function_template_generated_from.rel: delete
variable_template_generated_from.rel: delete
alias_template_generated_from.rel: delete

View File

@@ -1,36 +1,3 @@
## 10.2.0
### Deprecated APIs
* The `UsingAliasTypedefType` class has been deprecated. Use `TypeAliasType` instead.
### New Features
* Added a `getOriginalTemplate` predicate to `TemplateClass`, `TemplateFunction`, `TemplateVariable`, and `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 `AliasTemplateType` and `AliasTemplateInstantiationType` classes, representing C++ alias templates and their instantiations.
### Minor Analysis Improvements
* Added flow source models for `scanf_s` and related functions.
* Added a `Call` column to `LocalFlowSourceFunction::hasLocalFlowSource` and `RemoteFlowSourceFunction::hasRemoteFlowSource`. The old predicates without a `Call` column continue to be supported.
## 10.1.1
### Minor Analysis Improvements
* The `RemoteFlowSourceFunction` model for `fscanf` (and variants) now implements `hasSocketInput` to reflect that these functions may read from a socket.
## 10.1.0
### New Features
* A new predicate `getSwitchCase` was added to the `SwitchStmt` class, which yields the `n`th `case` statement from a `switch` statement.
* Data flow barriers and barrier guards can now be added using data extensions. For more information see [Customizing library models for C and C++](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-cpp/).
### Minor Analysis Improvements
* Added taint flow models for the `Strsafe.h` header from the Windows SDK.
## 10.0.0 ## 10.0.0
### Breaking Changes ### Breaking Changes

View File

@@ -30,6 +30,8 @@ class Options extends string {
predicate overrideReturnsNull(Call call) { predicate overrideReturnsNull(Call call) {
// Used in CVS: // Used in CVS:
call.(FunctionCall).getTarget().hasGlobalName("Xstrdup") call.(FunctionCall).getTarget().hasGlobalName("Xstrdup")
or
CustomOptions::overrideReturnsNull(call) // old Options.qll
} }
/** /**
@@ -43,6 +45,8 @@ class Options extends string {
// Used in CVS: // Used in CVS:
call.(FunctionCall).getTarget().hasGlobalName("Xstrdup") and call.(FunctionCall).getTarget().hasGlobalName("Xstrdup") and
nullValue(call.getArgument(0)) nullValue(call.getArgument(0))
or
CustomOptions::returnsNull(call) // old Options.qll
} }
/** /**
@@ -61,6 +65,8 @@ class Options extends string {
f.hasGlobalOrStdName([ f.hasGlobalOrStdName([
"exit", "_exit", "_Exit", "abort", "__assert_fail", "longjmp", "__builtin_unreachable" "exit", "_exit", "_Exit", "abort", "__assert_fail", "longjmp", "__builtin_unreachable"
]) ])
or
CustomOptions::exits(f) // old Options.qll
} }
/** /**
@@ -73,7 +79,8 @@ class Options extends string {
* runtime, the program's behavior is undefined) * runtime, the program's behavior is undefined)
*/ */
predicate exprExits(Expr e) { predicate exprExits(Expr e) {
e.(AssumeExpr).getChild(0).(CompileTimeConstantInt).getIntValue() = 0 e.(AssumeExpr).getChild(0).(CompileTimeConstantInt).getIntValue() = 0 or
CustomOptions::exprExits(e) // old Options.qll
} }
/** /**
@@ -81,7 +88,10 @@ class Options extends string {
* *
* By default holds only for `fgets`. * By default holds only for `fgets`.
*/ */
predicate alwaysCheckReturnValue(Function f) { f.hasGlobalOrStdName("fgets") } predicate alwaysCheckReturnValue(Function f) {
f.hasGlobalOrStdName("fgets") or
CustomOptions::alwaysCheckReturnValue(f) // old Options.qll
}
/** /**
* Holds if it is reasonable to ignore the return value of function * Holds if it is reasonable to ignore the return value of function
@@ -97,6 +107,8 @@ class Options extends string {
// common way of sleeping using select: // common way of sleeping using select:
fc.getTarget().hasGlobalName("select") and fc.getTarget().hasGlobalName("select") and
fc.getArgument(0).getValue() = "0" fc.getArgument(0).getValue() = "0"
or
CustomOptions::okToIgnoreReturnValue(fc) // old Options.qll
} }
} }

View File

@@ -98,3 +98,57 @@ class CustomMutexType extends MutexType {
*/ */
override predicate unlockAccess(FunctionCall fc, Expr arg) { none() } override predicate unlockAccess(FunctionCall fc, Expr arg) { none() }
} }
/**
* DEPRECATED: customize `CustomOptions.overrideReturnsNull` instead.
*
* This predicate is required to support backwards compatibility for
* older `Options.qll` files. It should not be removed or modified by
* end users.
*/
predicate overrideReturnsNull(Call call) { none() }
/**
* DEPRECATED: customize `CustomOptions.returnsNull` instead.
*
* This predicate is required to support backwards compatibility for
* older `Options.qll` files. It should not be removed or modified by
* end users.
*/
predicate returnsNull(Call call) { none() }
/**
* DEPRECATED: customize `CustomOptions.exits` instead.
*
* This predicate is required to support backwards compatibility for
* older `Options.qll` files. It should not be removed or modified by
* end users.
*/
predicate exits(Function f) { none() }
/**
* DEPRECATED: customize `CustomOptions.exprExits` instead.
*
* This predicate is required to support backwards compatibility for
* older `Options.qll` files. It should not be removed or modified by
* end users.
*/
predicate exprExits(Expr e) { none() }
/**
* DEPRECATED: customize `CustomOptions.alwaysCheckReturnValue` instead.
*
* This predicate is required to support backwards compatibility for
* older `Options.qll` files. It should not be removed or modified by
* end users.
*/
predicate alwaysCheckReturnValue(Function f) { none() }
/**
* DEPRECATED: customize `CustomOptions.okToIgnoreReturnValue` instead.
*
* This predicate is required to support backwards compatibility for
* older `Options.qll` files. It should not be removed or modified by
* end users.
*/
predicate okToIgnoreReturnValue(FunctionCall fc) { none() }

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Data flow barriers and barrier guards can now be added using data extensions. For more information see [Customizing library models for C and C++](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-cpp/).

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* A new predicate `getSwitchCase` was added to the `SwitchStmt` class, which yields the `n`th `case` statement from a `switch` statement.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added taint flow models for the `Strsafe.h` header from the Windows SDK.

View File

@@ -1,15 +0,0 @@
---
category: breaking
---
* Removed the deprecated `overrideReturnsNull` predicate from `Options.qll`. Use `CustomOptions.overrideReturnsNull` instead.
* Removed the deprecated `returnsNull` predicate from `Options.qll`. Use `CustomOptions.returnsNull` instead.
* Removed the deprecated `exits` predicate from `Options.qll`. Use `CustomOptions.exits` instead.
* Removed the deprecated `exprExits` predicate from `Options.qll`. Use `CustomOptions.exprExits` instead.
* Removed the deprecated `alwaysCheckReturnValue` predicate from `Options.qll`. Use `CustomOptions.alwaysCheckReturnValue` instead.
* Removed the deprecated `okToIgnoreReturnValue` predicate from `Options.qll`. Use `CustomOptions.okToIgnoreReturnValue` instead.
* Removed the deprecated `semmle.code.cpp.Member`. Import `semmle.code.cpp.Element` and/or `semmle.code.cpp.Type` directly.
* Removed the deprecated `UnknownDefaultLocation` class. Use `UnknownLocation` instead.
* Removed the deprecated `UnknownExprLocation` class. Use `UnknownLocation` instead.
* Removed the deprecated `UnknownStmtLocation` class. Use `UnknownLocation` instead.
* Removed the deprecated `TemplateParameter` class. Use `TypeTemplateParameter` instead.
* Support for class resolution across link targets has been removed for databases which were created with CodeQL versions before 1.23.0.

View File

@@ -1,10 +0,0 @@
## 10.1.0
### New Features
* A new predicate `getSwitchCase` was added to the `SwitchStmt` class, which yields the `n`th `case` statement from a `switch` statement.
* Data flow barriers and barrier guards can now be added using data extensions. For more information see [Customizing library models for C and C++](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-cpp/).
### Minor Analysis Improvements
* Added taint flow models for the `Strsafe.h` header from the Windows SDK.

View File

@@ -1,5 +0,0 @@
## 10.1.1
### Minor Analysis Improvements
* The `RemoteFlowSourceFunction` model for `fscanf` (and variants) now implements `hasSocketInput` to reflect that these functions may read from a socket.

View File

@@ -1,15 +0,0 @@
## 10.2.0
### Deprecated APIs
* The `UsingAliasTypedefType` class has been deprecated. Use `TypeAliasType` instead.
### New Features
* Added a `getOriginalTemplate` predicate to `TemplateClass`, `TemplateFunction`, `TemplateVariable`, and `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 `AliasTemplateType` and `AliasTemplateInstantiationType` classes, representing C++ alias templates and their instantiations.
### Minor Analysis Improvements
* Added flow source models for `scanf_s` and related functions.
* Added a `Call` column to `LocalFlowSourceFunction::hasLocalFlowSource` and `RemoteFlowSourceFunction::hasRemoteFlowSource`. The old predicates without a `Call` column continue to be supported.

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 10.2.0 lastReleaseVersion: 10.0.0

View File

@@ -32,6 +32,7 @@ import semmle.code.cpp.Class
import semmle.code.cpp.Struct import semmle.code.cpp.Struct
import semmle.code.cpp.Union import semmle.code.cpp.Union
import semmle.code.cpp.Enum import semmle.code.cpp.Enum
import semmle.code.cpp.Member
import semmle.code.cpp.Field import semmle.code.cpp.Field
import semmle.code.cpp.Function import semmle.code.cpp.Function
import semmle.code.cpp.MemberFunction import semmle.code.cpp.MemberFunction

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all name: codeql/cpp-all
version: 10.2.1-dev version: 10.0.1-dev
groups: cpp groups: cpp
dbscheme: semmlecode.cpp.dbscheme dbscheme: semmlecode.cpp.dbscheme
extractor: cpp extractor: cpp

View File

@@ -856,10 +856,8 @@ class AbstractClass extends Class {
/** /**
* A class template (this class also finds partial specializations * A class template (this class also finds partial specializations
* of class templates). * of class templates). For example in the following code there is a
* * `MyTemplateClass<T>` template:
* For example in the following code there is a `MyTemplateClass<T>`
* template:
* ``` * ```
* template<class T> * template<class T>
* class MyTemplateClass { * class MyTemplateClass {
@@ -895,29 +893,6 @@ class TemplateClass extends Class {
} }
override string getAPrimaryQlClass() { result = "TemplateClass" } override string getAPrimaryQlClass() { result = "TemplateClass" }
/**
* Gets the class member template this template was generated from.
*
* This predicate only has results for templates that are members of class
* template instantiations. For example, for `MyTemplateClass<int>::C<S>`
* in the following code, the result is `MyTemplateClass<T>::C<S>`.
* ```cpp
* template<class T>
* class MyTemplateClass {
* template<class S>
* class C {
* ...
* };
* };
*
* template
* class MyTemplateClass<int>;
* ```
*/
TemplateClass getOriginalTemplate() {
class_template_generated_from(underlyingElement(this), unresolveElement(result))
}
} }
/** /**

View File

@@ -278,8 +278,6 @@ class Declaration extends Locatable, @declaration {
or or
variable_template_argument(underlyingElement(this), index, unresolveElement(result)) variable_template_argument(underlyingElement(this), index, unresolveElement(result))
or or
alias_template_argument(underlyingElement(this), index, unresolveElement(result))
or
template_template_argument(underlyingElement(this), index, unresolveElement(result)) template_template_argument(underlyingElement(this), index, unresolveElement(result))
or or
concept_template_argument(underlyingElement(this), index, unresolveElement(result)) concept_template_argument(underlyingElement(this), index, unresolveElement(result))
@@ -292,8 +290,6 @@ class Declaration extends Locatable, @declaration {
or or
variable_template_argument_value(underlyingElement(this), index, unresolveElement(result)) variable_template_argument_value(underlyingElement(this), index, unresolveElement(result))
or or
alias_template_argument_value(underlyingElement(this), index, unresolveElement(result))
or
template_template_argument_value(underlyingElement(this), index, unresolveElement(result)) template_template_argument_value(underlyingElement(this), index, unresolveElement(result))
or or
concept_template_argument_value(underlyingElement(this), index, unresolveElement(result)) concept_template_argument_value(underlyingElement(this), index, unresolveElement(result))

View File

@@ -278,15 +278,6 @@ private predicate isFromTemplateInstantiationRec(Element e, Element instantiatio
instantiation.(Variable).isConstructedFrom(_) and instantiation.(Variable).isConstructedFrom(_) and
e = instantiation e = instantiation
or or
instantiation.(TypeAliasType).isConstructedFrom(_) and
e = instantiation
or
instantiation.(TemplateTemplateParameterInstantiation).isConstructedFrom(_) and
e = instantiation
or
exists(instantiation.(ConceptIdExpr).getConcept()) and
e = instantiation
or
isFromTemplateInstantiationRec(e.getEnclosingElement(), instantiation) isFromTemplateInstantiationRec(e.getEnclosingElement(), instantiation)
} }
@@ -300,15 +291,6 @@ private predicate isFromUninstantiatedTemplateRec(Element e, Element template) {
is_variable_template(unresolveElement(template)) and is_variable_template(unresolveElement(template)) and
e = template e = template
or or
is_alias_template(unresolveElement(template)) and
e = template
or
usertypes(unresolveElement(template), _, 8) and // template template parameter
e = template
or
template instanceof @concept_template and
e = template
or
isFromUninstantiatedTemplateRec(e.getEnclosingElement(), template) isFromUninstantiatedTemplateRec(e.getEnclosingElement(), template)
} }

View File

@@ -828,27 +828,6 @@ class TemplateFunction extends Function {
* such things -- see FunctionTemplateSpecialization for further details. * such things -- see FunctionTemplateSpecialization for further details.
*/ */
FunctionTemplateSpecialization getASpecialization() { result.getPrimaryTemplate() = this } FunctionTemplateSpecialization getASpecialization() { result.getPrimaryTemplate() = this }
/**
* Gets the class member template this template was generated from.
*
* This predicate only has results for templates that are members of class
* template instantiations. For example, for `MyTemplateClass<int>::f<S>`
* in the following code, the result is `MyTemplateClass<T>::f<S>`.
* ```cpp
* template<class T>
* class MyTemplateClass {
* template<class S>
* S f();
* };
*
* template
* class MyTemplateClass<int>;
* ```
*/
TemplateFunction getOriginalTemplate() {
function_template_generated_from(underlyingElement(this), unresolveElement(result))
}
} }
/** /**

View File

@@ -148,3 +148,28 @@ class UnknownLocation extends Location {
this.getFile().getAbsolutePath() = "" and locations_default(this, _, 0, 0, 0, 0) this.getFile().getAbsolutePath() = "" and locations_default(this, _, 0, 0, 0, 0)
} }
} }
/**
* A dummy location which is used when something doesn't have a location in
* the source code but needs to have a `Location` associated with it.
*
* DEPRECATED: use `UnknownLocation`
*/
deprecated class UnknownDefaultLocation extends UnknownLocation { }
/**
* A dummy location which is used when an expression doesn't have a
* location in the source code but needs to have a `Location` associated
* with it.
*
* DEPRECATED: use `UnknownLocation`
*/
deprecated class UnknownExprLocation extends UnknownLocation { }
/**
* A dummy location which is used when a statement doesn't have a location
* in the source code but needs to have a `Location` associated with it.
*
* DEPRECATED: use `UnknownLocation`
*/
deprecated class UnknownStmtLocation extends UnknownLocation { }

View File

@@ -0,0 +1,6 @@
/**
* DEPRECATED: import `semmle.code.cpp.Element` and/or `semmle.code.cpp.Type` directly as required.
*/
import semmle.code.cpp.Element
import semmle.code.cpp.Type

View File

@@ -35,6 +35,13 @@ class NonTypeTemplateParameter extends Literal, TemplateParameterImpl {
override string getAPrimaryQlClass() { result = "NonTypeTemplateParameter" } override string getAPrimaryQlClass() { result = "NonTypeTemplateParameter" }
} }
/**
* A C++ `typename` (or `class`) template parameter.
*
* DEPRECATED: Use `TypeTemplateParameter` instead.
*/
deprecated class TemplateParameter = TypeTemplateParameter;
/** /**
* A C++ `typename` (or `class`) template parameter. * A C++ `typename` (or `class`) template parameter.
* *

View File

@@ -1071,7 +1071,7 @@ class NullPointerType extends BuiltInType {
* const float fa[40]; * const float fa[40];
* ``` * ```
*/ */
class DerivedType extends Type, NameQualifyingElement, @derivedtype { class DerivedType extends Type, @derivedtype {
override string toString() { result = this.getName() } override string toString() { result = this.getName() }
override string getName() { derivedtypes(underlyingElement(this), result, _, _) } override string getName() { derivedtypes(underlyingElement(this), result, _, _) }

View File

@@ -64,123 +64,23 @@ class CTypedefType extends TypedefType {
} }
/** /**
* DEPRECATED: Use `TypeAlias` instead. * A using alias C++ typedef type. For example the type declared in the following code:
*
* A C++ type alias or alias template.
*
* For example the type declared in the following code:
* ``` * ```
* using my_int2 = int; * using my_int2 = int;
* ``` * ```
*/ */
deprecated class UsingAliasTypedefType = TypeAliasType; class UsingAliasTypedefType extends TypedefType {
UsingAliasTypedefType() { usertype_alias_kind(underlyingElement(this), 1) }
/** override string getAPrimaryQlClass() { result = "UsingAliasTypedefType" }
* A C++ type alias or alias template.
*
* For example the type declared in the following code:
* ```
* using my_int2 = int;
* ```
*/
class TypeAliasType extends TypedefType {
TypeAliasType() { usertype_alias_kind(underlyingElement(this), 1) }
override string getAPrimaryQlClass() { result = "TypeAliasType" }
override string explain() { override string explain() {
result = "using {" + this.getBaseType().explain() + "} as \"" + this.getName() + "\"" result = "using {" + this.getBaseType().explain() + "} as \"" + this.getName() + "\""
} }
/**
* Holds if this alias is constructed from another alias as a result of
* template instantiation.
*/
predicate isConstructedFrom(TypeAliasType t) {
alias_instantiation(underlyingElement(this), unresolveElement(t))
}
} }
/** /**
* A C++ alias template. * A C++ `typedef` type that is directly enclosed by a function. For example the type declared inside the function `foo` in
*
* For example the type declared in the following code:
* ```
* template <typename T>
* using my_type = T;
* ```
*/
class AliasTemplateType extends TypeAliasType {
AliasTemplateType() { is_alias_template(underlyingElement(this)) }
override string getAPrimaryQlClass() { result = "AliasTemplateType" }
/**
* Gets an alias instantiated from this template.
*
* For example for `MyAliasTemplate<T>` in the following code, the results are
* `MyAliasTemplate<int>` and `MyAliasTemplate<long>`:
* ```
* template<typename T>
* using MyAliasTemplate = ...;
*
* MyAliasTemplate<int> instance1;
*
* MyAliasTemplate<long> instance2;
* ```
*/
TypeAliasType getAnInstantiation() { result.isConstructedFrom(this) }
/**
* Gets the class member template this template was generated from.
*
* This predicate only has results for templates that are members of class
* template instantiations. For example, for `MyTemplateClass<int>::t<S>`
* in the following code, the result is `MyTemplateClass<T>::t<S>`.
* ```cpp
* template<class T>
* class MyTemplateClass {
* template<class S>
* using t = S;
* };
*
* template
* class MyTemplateClass<int>;
* ```
*/
AliasTemplateType getOriginalTemplate() {
alias_template_generated_from(underlyingElement(this), unresolveElement(result))
}
}
/**
* A C++ alias template instantiation.
*
* For example the `my_int_type` type declared in the following code:
* ```
* template <typename T>
* using my_type = T;
*
* using my_int_type = my_type<int>;
* ```
*/
class AliasTemplateInstantiationType extends TypeAliasType {
AliasTemplateType at;
AliasTemplateInstantiationType() { at.getAnInstantiation() = this }
override string getAPrimaryQlClass() { result = "AliasTemplateInstantiationType" }
/**
* Gets the alias template from which this instantiation was instantiated.
*/
AliasTemplateType getTemplate() { result = at }
}
/**
* A C++ `typedef` type that is directly enclosed by a function.
*
* For example the type declared inside the function `foo` in
* the following code: * the following code:
* ``` * ```
* int foo(void) { typedef int local; } * int foo(void) { typedef int local; }

View File

@@ -614,27 +614,6 @@ class TemplateVariable extends Variable {
result.isConstructedFrom(this) and result.isConstructedFrom(this) and
not result.isSpecialization() not result.isSpecialization()
} }
/**
* Gets the class member template this template was generated from.
*
* This predicate only has results for templates that are members of class
* template instantiations. For example, for `MyTemplateClass<int>::x<S>`
* in the following code, the result is `MyTemplateClass<T>::x<S>`.
* ```cpp
* template<class T>
* class MyTemplateClass {
* template<class S>
* static S x;
* };
*
* template
* class MyTemplateClass<int>;
* ```
*/
TemplateVariable getOriginalTemplate() {
variable_template_generated_from(underlyingElement(this), unresolveElement(result))
}
} }
/** /**

View File

@@ -25,15 +25,6 @@ abstract class ScanfFunction extends Function {
* (rather than a `char*`). * (rather than a `char*`).
*/ */
predicate isWideCharDefault() { exists(this.getName().indexOf("wscanf")) } predicate isWideCharDefault() { exists(this.getName().indexOf("wscanf")) }
/** Holds if this is one of the `scanf_s` variants. */
predicate isSVariant() {
exists(string name | name = this.getName() |
name.matches("%\\_s")
or
name.matches("%\\_s\\_l")
)
}
} }
/** /**
@@ -43,12 +34,8 @@ class Scanf extends ScanfFunction instanceof TopLevelFunction {
Scanf() { Scanf() {
this.hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...) this.hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...)
this.hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...) this.hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...)
this.hasGlobalOrStdOrBslName("scanf_s") or // scanf_s(format, args...)
this.hasGlobalOrStdOrBslName("wscanf_s") or // wscanf_s(format, args...)
this.hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...) this.hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...)
this.hasGlobalName("_wscanf_l") or // _wscanf_l(format, locale, args...) this.hasGlobalName("_wscanf_l")
this.hasGlobalName("_scanf_s_l") or // _scanf_s_l(format, locale, args...)
this.hasGlobalName("_wscanf_s_l") // _wscanf_s_l(format, locale, args...)
} }
override int getInputParameterIndex() { none() } override int getInputParameterIndex() { none() }
@@ -63,12 +50,8 @@ class Fscanf extends ScanfFunction instanceof TopLevelFunction {
Fscanf() { Fscanf() {
this.hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...) this.hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...)
this.hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...) this.hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...)
this.hasGlobalOrStdOrBslName("fscanf_s") or // fscanf_s(src_stream, format, args...)
this.hasGlobalOrStdOrBslName("fwscanf_s") or // fwscanf_s(src_stream, format, args...)
this.hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...) this.hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...)
this.hasGlobalName("_fwscanf_l") or // _fwscanf_l(src_stream, format, locale, args...) this.hasGlobalName("_fwscanf_l")
this.hasGlobalName("_fscanf_s_l") or // _fscanf_s_l(src_stream, format, locale, args...)
this.hasGlobalName("_fwscanf_s_l") // _fwscanf_s_l(src_stream, format, locale, args...)
} }
override int getInputParameterIndex() { result = 0 } override int getInputParameterIndex() { result = 0 }
@@ -83,12 +66,8 @@ class Sscanf extends ScanfFunction instanceof TopLevelFunction {
Sscanf() { Sscanf() {
this.hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...) this.hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...)
this.hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...) this.hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...)
this.hasGlobalOrStdOrBslName("sscanf_s") or // sscanf_s(src, format, args...)
this.hasGlobalOrStdOrBslName("swscanf_s") or // swscanf_s(src, format, args...)
this.hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...) this.hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...)
this.hasGlobalName("_swscanf_l") or // _swscanf_l(src, format, locale, args...) this.hasGlobalName("_swscanf_l")
this.hasGlobalName("_sscanf_s_l") or // _sscanf_s_l(src, format, locale, args...)
this.hasGlobalName("_swscanf_s_l") // _swscanf_s_l(src, format, locale, args...)
} }
override int getInputParameterIndex() { result = 0 } override int getInputParameterIndex() { result = 0 }
@@ -118,14 +97,6 @@ class Snscanf extends ScanfFunction instanceof TopLevelFunction {
int getInputLengthParameterIndex() { result = 1 } int getInputLengthParameterIndex() { result = 1 }
} }
private predicate isCharLike(Type t) { t instanceof CharType or t instanceof Wchar_t }
private predicate isStringLike(Type t) {
isCharLike(t.(PointerType).getBaseType())
or
isCharLike(t.(ArrayType).getBaseType())
}
/** /**
* A call to one of the `scanf` functions. * A call to one of the `scanf` functions.
*/ */
@@ -159,40 +130,14 @@ class ScanfFunctionCall extends FunctionCall {
*/ */
predicate isWideCharDefault() { this.getScanfFunction().isWideCharDefault() } predicate isWideCharDefault() { this.getScanfFunction().isWideCharDefault() }
bindingset[this, k]
pragma[inline_late]
private predicate isSizeArgument(int k) {
// The first vararg is never the size argument since a size argument must
// always follow a string buffer argument.
k > 0 and
isStringLike(this.getArgument(this.getScanfFunction().getNumberOfParameters() + k - 1)
.getUnspecifiedType())
}
/** /**
* Gets the output argument at position `n` in the vararg list of this call. * Gets the output argument at position `n` in the vararg list of this call.
* *
* The range of `n` is from `0` to `this.getNumberOfOutputArguments() - 1`. * The range of `n` is from `0` to `this.getNumberOfOutputArguments() - 1`.
*/ */
Expr getOutputArgument(int n) { Expr getOutputArgument(int n) {
exists(ScanfFunction target | target = this.getScanfFunction() | result = this.getArgument(this.getTarget().getNumberOfParameters() + n) and
// If this is an S variant then every string buffer argument has a n >= 0
// corresponding size argument immediately following it, so we need to
// skip over those size arguments when counting the output arguments.
if target.isSVariant()
then
result =
rank[n + 1](Expr arg, int k |
k >= 0 and
arg = this.getArgument(target.getNumberOfParameters() + k) and
not this.isSizeArgument(k)
|
arg order by k
)
else (
n >= 0 and result = this.getArgument(target.getNumberOfParameters() + n)
)
)
} }
/** /**

View File

@@ -276,45 +276,6 @@ private predicate isClassConstructedFrom(Class c, Class templateClass) {
not c.isConstructedFrom(_) and c = templateClass not c.isConstructedFrom(_) and c = templateClass
} }
/** Gets the fully templated version of `c`. */
private Class getFullyTemplatedClassOld(Class c) {
not c.isFromUninstantiatedTemplate(_) and
isClassConstructedFrom(c, result)
}
private TemplateClass getOriginalClassTemplate(TemplateClass tc) {
result = tc.getOriginalTemplate()
or
not exists(tc.getOriginalTemplate()) and
result = tc
}
/** Gets the fully templated version of `c`. */
private Class getFullyTemplatedClassNew(Class c) {
not c.isFromUninstantiatedTemplate(_) and
exists(Class mid |
c.isConstructedFrom(mid)
or
not c.isConstructedFrom(_) and c = mid
|
result = getOriginalClassTemplate(mid)
or
not mid instanceof TemplateClass and mid = result
)
}
/** Gets the fully templated version of `c`. */
private Class getFullyTemplatedClass(Class c) {
// The `Class::getOriginalTemplate` predicate was introduced in CodeQL
// version 2.25.6 and the upgrade script leaves the
// `class_template_generated_from` extensionals empty if the database
// was generated with an older extractor. So we use the old implementation
// if the `class_template_generated_from` extensional is empty.
if class_template_generated_from(_, _)
then result = getFullyTemplatedClassNew(c)
else result = getFullyTemplatedClassOld(c)
}
/** /**
* Holds if `f` is an instantiation of a function template `templateFunc`, or * Holds if `f` is an instantiation of a function template `templateFunc`, or
* holds with `f = templateFunc` if `f` is not an instantiation of any function * holds with `f = templateFunc` if `f` is not an instantiation of any function
@@ -331,7 +292,7 @@ private predicate isFunctionConstructedFrom(Function f, Function templateFunc) {
} }
/** Gets the fully templated version of `f`. */ /** Gets the fully templated version of `f`. */
private Function getFullyTemplatedFunctionOld(Function f) { Function getFullyTemplatedFunction(Function f) {
not f.isFromUninstantiatedTemplate(_) and not f.isFromUninstantiatedTemplate(_) and
( (
exists(Class c, Class templateClass, int i | exists(Class c, Class templateClass, int i |
@@ -345,46 +306,13 @@ private Function getFullyTemplatedFunctionOld(Function f) {
) )
} }
private TemplateFunction getOriginalFunctionTemplate(TemplateFunction tf) {
result = tf.getOriginalTemplate()
or
not exists(tf.getOriginalTemplate()) and
result = tf
}
/** Gets the fully templated version of `f`. */
private Function getFullyTemplatedFunctionNew(Function f) {
not f.isFromUninstantiatedTemplate(_) and
exists(Function mid |
f.isConstructedFrom(mid)
or
not f.isConstructedFrom(_) and f = mid
|
result = getOriginalFunctionTemplate(mid)
or
not mid instanceof TemplateFunction and mid = result
)
}
/** Gets the fully templated version of `f`. */
Function getFullyTemplatedFunction(Function f) {
// The `Function::getOriginalTemplate` predicate was introduced in CodeQL
// version 2.25.6 and the upgrade script leaves the
// `function_template_generated_from` extensionals empty if the database
// was generated with an older extractor. So we use the old implementation
// if the `function_template_generated_from` extensional is empty.
if function_template_generated_from(_, _)
then result = getFullyTemplatedFunctionNew(f)
else result = getFullyTemplatedFunctionOld(f)
}
/** Prefixes `const` to `s` if `t` is const, or returns `s` otherwise. */ /** Prefixes `const` to `s` if `t` is const, or returns `s` otherwise. */
bindingset[s, t] bindingset[s, t]
private string withConst(string s, Type t) { private string withConst(string s, Type t) {
if t.isConst() then result = "const " + s else result = s if t.isConst() then result = "const " + s else result = s
} }
/** Prefixes `volatile` to `s` if `t` is volatile, or returns `s` otherwise. */ /** Prefixes `volatile` to `s` if `t` is const, or returns `s` otherwise. */
bindingset[s, t] bindingset[s, t]
private string withVolatile(string s, Type t) { private string withVolatile(string s, Type t) {
if t.isVolatile() then result = "volatile " + s else result = s if t.isVolatile() then result = "volatile " + s else result = s
@@ -562,7 +490,7 @@ pragma[nomagic]
private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining) { private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining) {
// If there is a declaring type then we start by expanding the function templates // If there is a declaring type then we start by expanding the function templates
exists(Class template | exists(Class template |
template = getFullyTemplatedClass(f.getDeclaringType()) and isClassConstructedFrom(f.getDeclaringType(), template) and
remaining = getNumberOfSupportedClassTemplateArguments(template) and remaining = getNumberOfSupportedClassTemplateArguments(template) and
result = getTypeNameWithoutFunctionTemplates(f, n, 0) result = getTypeNameWithoutFunctionTemplates(f, n, 0)
) )
@@ -574,7 +502,7 @@ private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining
or or
exists(string mid, TypeTemplateParameter tp, Class template | exists(string mid, TypeTemplateParameter tp, Class template |
mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and
template = getFullyTemplatedClass(f.getDeclaringType()) and isClassConstructedFrom(f.getDeclaringType(), template) and
tp = getSupportedClassTemplateArgument(template, remaining) tp = getSupportedClassTemplateArgument(template, remaining)
| |
result = mid.replaceAll(tp.getName(), "class:" + remaining.toString()) result = mid.replaceAll(tp.getName(), "class:" + remaining.toString())

View File

@@ -1,5 +1,59 @@
import semmle.code.cpp.Type import semmle.code.cpp.Type
/** For upgraded databases without mangled name info. */
pragma[noinline]
private string getTopLevelClassName(@usertype c) {
not mangled_name(_, _, _) and
isClass(c) and
usertypes(c, result, _) and
not namespacembrs(_, c) and // not in a namespace
not member(_, _, c) and // not in some structure
not class_instantiation(c, _) // not a template instantiation
}
/**
* For upgraded databases without mangled name info.
* Holds if `d` is a unique complete class named `name`.
*/
pragma[noinline]
private predicate existsCompleteWithName(string name, @usertype d) {
not mangled_name(_, _, _) and
is_complete(d) and
name = getTopLevelClassName(d) and
onlyOneCompleteClassExistsWithName(name)
}
/** For upgraded databases without mangled name info. */
pragma[noinline]
private predicate onlyOneCompleteClassExistsWithName(string name) {
not mangled_name(_, _, _) and
strictcount(@usertype c | is_complete(c) and getTopLevelClassName(c) = name) = 1
}
/**
* For upgraded databases without mangled name info.
* Holds if `c` is an incomplete class named `name`.
*/
pragma[noinline]
private predicate existsIncompleteWithName(string name, @usertype c) {
not mangled_name(_, _, _) and
not is_complete(c) and
name = getTopLevelClassName(c)
}
/**
* For upgraded databases without mangled name info.
* Holds if `c` is an incomplete class, and there exists a unique complete class `d`
* with the same name.
*/
private predicate oldHasCompleteTwin(@usertype c, @usertype d) {
not mangled_name(_, _, _) and
exists(string name |
existsIncompleteWithName(name, c) and
existsCompleteWithName(name, d)
)
}
pragma[noinline] pragma[noinline]
private @mangledname getClassMangledName(@usertype c) { private @mangledname getClassMangledName(@usertype c) {
isClass(c) and isClass(c) and
@@ -49,7 +103,10 @@ private module Cached {
@usertype resolveClass(@usertype c) { @usertype resolveClass(@usertype c) {
hasCompleteTwin(c, result) hasCompleteTwin(c, result)
or or
oldHasCompleteTwin(c, result)
or
not hasCompleteTwin(c, _) and not hasCompleteTwin(c, _) and
not oldHasCompleteTwin(c, _) and
result = c result = c
} }

View File

@@ -136,9 +136,7 @@ private module SourceVariables {
NormalSourceVariable() { this = TNormalSourceVariable(base, ind) } NormalSourceVariable() { this = TNormalSourceVariable(base, ind) }
final override string toString() { final override string toString() {
if this.getIndirection() = 0 result = repeatStars(this.getIndirection()) + base.toString()
then result = "&" + base.toString()
else result = repeatStars(this.getIndirection() - 1) + base.toString()
} }
} }
@@ -159,9 +157,7 @@ private module SourceVariables {
} }
final override string toString() { final override string toString() {
if this.getIndirection() = 0 result = repeatStars(this.getIndirection()) + base.toString() + " [before crement]"
then result = "&" + base.toString() + " [before crement]"
else result = repeatStars(this.getIndirection() - 1) + base.toString() + " [before crement]"
} }
/** /**
@@ -1357,52 +1353,6 @@ class PhiNode extends Definition instanceof SsaImpl::PhiNode {
final predicate hasInputFromBlock(Definition input, IRBlock bb) { final predicate hasInputFromBlock(Definition input, IRBlock bb) {
phiHasInputFromBlock(this, input, bb) phiHasInputFromBlock(this, input, bb)
} }
override int getIndirection() { result = this.getSourceVariable().getIndirection() }
override predicate isCertain() {
// If this phi node is part of a phi cycle of phi nodes the least
// fixed-point semantics of datalog means we don't get the right answer.
// So we perform an SCC reduction to simulate greatest fixed-point semantics.
getCycle(this).isCertain()
or
// If there is no cycle we get the right semantics through traditional
// recursion.
not exists(getCycle(this)) and
forex(Definition inp | inp = this.getAnInput() | inp.isCertain())
}
final override Declaration getFunction() {
result = SsaImpl::PhiNode.super.getBasicBlock().getEnclosingFunction()
}
}
private PhiNode getAnInput(PhiNode phi) { result = phi.getAnInput() }
private predicate sccEdge(PhiNode phi1, PhiNode phi2) {
getAnInput(phi1) = phi2 and getAnInput+(phi2) = phi1
}
private module PhiCycleEquivalence = QlBuiltins::EquivalenceRelation<PhiNode, sccEdge/2>;
private PhiCycle getCycle(PhiNode phi) { result.getAPhiNode() = phi }
private class PhiCycle extends PhiCycleEquivalence::EquivalenceClass {
PhiNode getAPhiNode() { PhiCycleEquivalence::getEquivalenceClass(result) = this }
predicate hasPhiNode(PhiNode phi) { this.getAPhiNode() = phi }
pragma[nomagic]
Definition getAnInput() {
result = this.getAPhiNode().getAnInput() and not this.hasPhiNode(result)
}
string toString() { result = strictconcat(this.getAPhiNode().toString(), ", ") }
predicate isCertain() {
// A phi cycle is certain if all of the inputs into the phi cycle is certain.
forex(Definition inp | inp = this.getAnInput() | inp.isCertain())
}
} }
/** An static single assignment (SSA) definition. */ /** An static single assignment (SSA) definition. */

View File

@@ -147,7 +147,7 @@ abstract class Indirection extends Type {
* *
* `certain` is `true` if this write is guaranteed to write to the address. * `certain` is `true` if this write is guaranteed to write to the address.
*/ */
predicate isAdditionalWrite(Node0Impl value, Operand address, Certainty certain) { none() } predicate isAdditionalWrite(Node0Impl value, Operand address, boolean certain) { none() }
/** /**
* Gets the base type of this indirection, after specifiers have been deeply * Gets the base type of this indirection, after specifiers have been deeply
@@ -198,11 +198,11 @@ private module IteratorIndirections {
baseType = super.getValueType() baseType = super.getValueType()
} }
override predicate isAdditionalWrite(Node0Impl value, Operand address, Certainty certain) { override predicate isAdditionalWrite(Node0Impl value, Operand address, boolean certain) {
exists(CallInstruction call | call.getArgumentOperand(0) = value.asOperand() | exists(CallInstruction call | call.getArgumentOperand(0) = value.asOperand() |
this = call.getStaticCallTarget().(Function).getClassAndName("operator=") and this = call.getStaticCallTarget().(Function).getClassAndName("operator=") and
address = call.getThisArgumentOperand() and address = call.getThisArgumentOperand() and
certain instanceof AlwaysUncertain certain = false
) )
} }
@@ -271,62 +271,30 @@ predicate isDereference(Instruction deref, Operand address, boolean additional)
additional = false additional = false
} }
private newtype TCertainty = predicate isWrite(Node0Impl value, Operand address, boolean certain) {
TCertainWhenAddressIsCertain() or
TAlwaysCertain() or
TAlwaysUncertain()
abstract private class Certainty extends TCertainty {
abstract predicate isCertain(boolean addressIsCertain);
abstract string toString();
}
private class CertainWhenAddressIsCertain extends Certainty, TCertainWhenAddressIsCertain {
override predicate isCertain(boolean addressIsCertain) { addressIsCertain = true }
override string toString() { result = "CertainWhenAddressIsCertain" }
}
private class AlwaysCertain extends Certainty, TAlwaysCertain {
override predicate isCertain(boolean addressIsCertain) {
addressIsCertain = true or addressIsCertain = false
}
override string toString() { result = "AlwaysCertain" }
}
private class AlwaysUncertain extends Certainty, TAlwaysUncertain {
override predicate isCertain(boolean addressIsCertain) { none() }
override string toString() { result = "AlwaysUncertain" }
}
predicate isWrite(Node0Impl value, Operand address, Certainty certain) {
any(Indirection ind).isAdditionalWrite(value, address, certain) any(Indirection ind).isAdditionalWrite(value, address, certain)
or or
exists(StoreInstruction store | certain = true and
value.asInstruction() = store and (
address = store.getDestinationAddressOperand() and exists(StoreInstruction store |
certain instanceof CertainWhenAddressIsCertain value.asInstruction() = store and
) address = store.getDestinationAddressOperand()
or )
exists(InitializeParameterInstruction init | or
value.asInstruction() = init and exists(InitializeParameterInstruction init |
address = init.getAnOperand() and value.asInstruction() = init and
certain instanceof AlwaysCertain address = init.getAnOperand()
) )
or or
exists(InitializeDynamicAllocationInstruction init | exists(InitializeDynamicAllocationInstruction init |
value.asInstruction() = init and value.asInstruction() = init and
address = init.getAllocationAddressOperand() and address = init.getAllocationAddressOperand()
certain instanceof AlwaysCertain )
) or
or exists(UninitializedInstruction uninitialized |
exists(UninitializedInstruction uninitialized | value.asInstruction() = uninitialized and
value.asInstruction() = uninitialized and address = uninitialized.getAnOperand()
address = uninitialized.getAnOperand() and )
certain instanceof AlwaysCertain
) )
} }
@@ -750,18 +718,16 @@ private module Cached {
int indirectionIndex int indirectionIndex
) { ) {
exists( exists(
Certainty writeIsCertain, boolean addressIsCertain, int ind0, CppType type, int lower, boolean writeIsCertain, boolean addressIsCertain, int ind0, CppType type, int lower, int upper
int upper
| |
isWrite(value, address, writeIsCertain) and isWrite(value, address, writeIsCertain) and
isDefImpl(address, base, ind0, addressIsCertain) and isDefImpl(address, base, ind0, addressIsCertain) and
certain = writeIsCertain.booleanAnd(addressIsCertain) and
type = getLanguageType(address) and type = getLanguageType(address) and
upper = countIndirectionsForCppType(type) and upper = countIndirectionsForCppType(type) and
ind = ind0 + [lower .. upper] and ind = ind0 + [lower .. upper] and
indirectionIndex = ind - (ind0 + lower) and indirectionIndex = ind - (ind0 + lower) and
lower = getMinIndirectionsForType(any(Type t | type.hasUnspecifiedType(t, _))) lower = getMinIndirectionsForType(any(Type t | type.hasUnspecifiedType(t, _)))
|
if writeIsCertain.isCertain(addressIsCertain) then certain = true else certain = false
) )
} }

View File

@@ -11,9 +11,7 @@ private class Fopen extends Function, AliasFunction, SideEffectFunction, TaintFu
Fopen() { Fopen() {
this.hasGlobalOrStdName(["fopen", "fopen_s", "freopen"]) this.hasGlobalOrStdName(["fopen", "fopen_s", "freopen"])
or or
this.hasGlobalName([ this.hasGlobalName(["_open", "_wfopen", "_fsopen", "_wfsopen", "_wopen"])
"_open", "_wfopen", "_fsopen", "_wfsopen", "_wopen", "_sopen_s", "_wsopen_s"
])
} }
override predicate hasOnlySpecificWriteSideEffects() { any() } override predicate hasOnlySpecificWriteSideEffects() { any() }
@@ -48,10 +46,6 @@ private class Fopen extends Function, AliasFunction, SideEffectFunction, TaintFu
this.hasGlobalName(["_open", "_wopen"]) and this.hasGlobalName(["_open", "_wopen"]) and
i = 0 and i = 0 and
buffer = true buffer = true
or
this.hasGlobalName(["_sopen_s", "_wsopen_s"]) and
i = 1 and
buffer = true
} }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -70,9 +64,5 @@ private class Fopen extends Function, AliasFunction, SideEffectFunction, TaintFu
this.hasGlobalName(["_open", "_wopen"]) and this.hasGlobalName(["_open", "_wopen"]) and
input.isParameterDeref(0) and input.isParameterDeref(0) and
output.isReturnValue() output.isReturnValue()
or
this.hasGlobalName(["_sopen_s", "_wsopen_s"]) and
input.isParameterDeref(1) and
output.isParameterDeref(0)
} }
} }

View File

@@ -30,10 +30,7 @@ abstract private class ScanfFunctionModel extends ArrayFunction, TaintFunction,
( (
if exists(this.getLengthParameterIndex()) if exists(this.getLengthParameterIndex())
then result = this.getLengthParameterIndex() + 2 then result = this.getLengthParameterIndex() + 2
else else result = 2
if exists(this.(ScanfFunction).getInputParameterIndex())
then result = 2
else result = 1
) )
} }
@@ -72,24 +69,13 @@ abstract private class ScanfFunctionModel extends ArrayFunction, TaintFunction,
} }
} }
private predicate hasFlowSource(
ScanfFunction func, ScanfFunctionCall call, FunctionOutput output, string description
) {
exists(int n, Expr arg |
call.getScanfFunction() = func and
call.getOutputArgument(_) = arg and
call.getArgument(n) = arg and
output.isParameterDeref(n) and
description = "value read by " + func.getName()
)
}
/** /**
* The standard function `scanf` and its assorted variants * The standard function `scanf` and its assorted variants
*/ */
private class ScanfModel extends ScanfFunctionModel, LocalFlowSourceFunction instanceof Scanf { private class ScanfModel extends ScanfFunctionModel, LocalFlowSourceFunction instanceof Scanf {
override predicate hasLocalFlowSource(Call call, FunctionOutput output, string description) { override predicate hasLocalFlowSource(FunctionOutput output, string description) {
hasFlowSource(this, call, output, description) output.isParameterDeref(any(int i | i >= this.getArgsStartPosition())) and
description = "value read by " + this.getName()
} }
} }
@@ -97,12 +83,9 @@ private class ScanfModel extends ScanfFunctionModel, LocalFlowSourceFunction ins
* The standard function `fscanf` and its assorted variants * The standard function `fscanf` and its assorted variants
*/ */
private class FscanfModel extends ScanfFunctionModel, RemoteFlowSourceFunction instanceof Fscanf { private class FscanfModel extends ScanfFunctionModel, RemoteFlowSourceFunction instanceof Fscanf {
override predicate hasRemoteFlowSource(Call call, FunctionOutput output, string description) { override predicate hasRemoteFlowSource(FunctionOutput output, string description) {
hasFlowSource(this, call, output, description) output.isParameterDeref(any(int i | i >= this.getArgsStartPosition())) and
} description = "value read by " + this.getName()
override predicate hasSocketInput(FunctionInput input) {
input.isParameterDeref(super.getInputParameterIndex())
} }
} }

View File

@@ -18,17 +18,7 @@ abstract class RemoteFlowSourceFunction extends Function {
/** /**
* Holds if remote data described by `description` flows from `output` of a call to this function. * Holds if remote data described by `description` flows from `output` of a call to this function.
*/ */
predicate hasRemoteFlowSource(FunctionOutput output, string description) { abstract predicate hasRemoteFlowSource(FunctionOutput output, string description);
this.hasRemoteFlowSource(_, output, description)
}
/**
* Holds if remote data described by `description` flows from `output` of `call` to this function.
*/
predicate hasRemoteFlowSource(Call call, FunctionOutput output, string description) {
call.getTarget() = this and
this.hasRemoteFlowSource(output, description)
}
/** /**
* Holds if remote data from this source comes from a socket or stream * Holds if remote data from this source comes from a socket or stream
@@ -45,17 +35,7 @@ abstract class LocalFlowSourceFunction extends Function {
/** /**
* Holds if data described by `description` flows from `output` of a call to this function. * Holds if data described by `description` flows from `output` of a call to this function.
*/ */
predicate hasLocalFlowSource(FunctionOutput output, string description) { abstract predicate hasLocalFlowSource(FunctionOutput output, string description);
this.hasLocalFlowSource(_, output, description)
}
/**
* Holds if data described by `description` flows from `output` of `call` to this function.
*/
predicate hasLocalFlowSource(Call call, FunctionOutput output, string description) {
call.getTarget() = this and
this.hasLocalFlowSource(output, description)
}
} }
/** A library function that sends data over a network connection. */ /** A library function that sends data over a network connection. */

View File

@@ -28,7 +28,8 @@ private class RemoteModelSource extends RemoteFlowSource {
RemoteModelSource() { RemoteModelSource() {
exists(CallInstruction call, RemoteFlowSourceFunction func, FunctionOutput output | exists(CallInstruction call, RemoteFlowSourceFunction func, FunctionOutput output |
func.hasRemoteFlowSource(call.getConvertedResultExpression(), output, sourceType) and call.getStaticCallTarget() = func and
func.hasRemoteFlowSource(output, sourceType) and
this = callOutput(call, output) this = callOutput(call, output)
) )
} }
@@ -45,7 +46,7 @@ private class LocalModelSource extends LocalFlowSource {
LocalModelSource() { LocalModelSource() {
exists(CallInstruction call, LocalFlowSourceFunction func, FunctionOutput output | exists(CallInstruction call, LocalFlowSourceFunction func, FunctionOutput output |
call.getStaticCallTarget() = func and call.getStaticCallTarget() = func and
func.hasLocalFlowSource(call.getConvertedResultExpression(), output, sourceType) and func.hasLocalFlowSource(output, sourceType) and
this = callOutput(call, output) this = callOutput(call, output)
) )
} }

View File

@@ -912,10 +912,6 @@ class_template_argument_value(
int index: int ref, int index: int ref,
int arg_value: @expr ref int arg_value: @expr ref
); );
class_template_generated_from(
unique int template: @usertype ref,
int from: @usertype ref
)
@user_or_decltype = @usertype | @decltype; @user_or_decltype = @usertype | @decltype;
@@ -947,10 +943,6 @@ function_template_argument_value(
int index: int ref, int index: int ref,
int arg_value: @expr ref int arg_value: @expr ref
); );
function_template_generated_from(
unique int template: @function ref,
int from: @function ref
);
is_variable_template(unique int id: @variable ref); is_variable_template(unique int id: @variable ref);
variable_instantiation( variable_instantiation(
@@ -967,30 +959,6 @@ variable_template_argument_value(
int index: int ref, int index: int ref,
int arg_value: @expr ref int arg_value: @expr ref
); );
variable_template_generated_from(
unique int template: @variable ref,
int from: @variable ref
);
is_alias_template(unique int id: @usertype ref);
alias_instantiation(
unique int to: @usertype ref,
int from: @usertype ref
);
alias_template_argument(
int type_id: @usertype ref,
int index: int ref,
int arg_type: @type ref
);
alias_template_argument_value(
int type_id: @usertype ref,
int index: int ref,
int arg_value: @expr ref
);
alias_template_generated_from(
unique int template: @usertype ref,
int from: @usertype ref
);
template_template_instantiation( template_template_instantiation(
int to: @usertype ref, int to: @usertype ref,
@@ -1430,8 +1398,7 @@ specialnamequalifyingelements(
@namequalifyingelement = @namespace @namequalifyingelement = @namespace
| @specialnamequalifyingelement | @specialnamequalifyingelement
| @usertype | @usertype
| @decltype | @decltype;
| @derivedtype;
namequalifiers( namequalifiers(
unique int id: @namequalifier, unique int id: @namequalifier,

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +0,0 @@
description: Support alias templates
compatibility: backwards

View File

@@ -1,2 +0,0 @@
description: Capture information about one template being generated from another
compatibility: backwards

View File

@@ -1,2 +0,0 @@
description: Fix NameQualifier inconsistency
compatibility: full

View File

@@ -1,17 +1,3 @@
## 1.6.4
No user-facing changes.
## 1.6.3
### Minor Analysis Improvements
* The 'Cleartext transmission of sensitive information' query (`cpp/cleartext-transmission`) no longer raises an alert on calls to `fscanf` (and variants) when the call reads from an "obviously local" `FILE` stream such as `stdin`.
## 1.6.2
No user-facing changes.
## 1.6.1 ## 1.6.1
### Minor Analysis Improvements ### Minor Analysis Improvements

View File

@@ -44,7 +44,10 @@ class ExternalApiDataNode extends DataFlow::Node {
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */ /** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { predicate isSource(DataFlow::Node source) {
any(RemoteFlowSourceFunction remoteFlow).hasRemoteFlowSource(source.asExpr(), _, _) exists(RemoteFlowSourceFunction remoteFlow |
remoteFlow = source.asExpr().(Call).getTarget() and
remoteFlow.hasRemoteFlowSource(_, _)
)
} }
predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }

View File

@@ -94,8 +94,9 @@ class Recv extends SendRecv instanceof RemoteFlowSourceFunction {
} }
override Expr getDataExpr(Call call) { override Expr getDataExpr(Call call) {
call.getTarget() = this and
exists(FunctionOutput output, int arg | exists(FunctionOutput output, int arg |
super.hasRemoteFlowSource(call, output, _) and super.hasRemoteFlowSource(output, _) and
output.isParameterDeref(arg) and output.isParameterDeref(arg) and
result = call.getArgument(arg) result = call.getArgument(arg)
) )

View File

@@ -1,3 +0,0 @@
## 1.6.2
No user-facing changes.

View File

@@ -1,5 +0,0 @@
## 1.6.3
### Minor Analysis Improvements
* The 'Cleartext transmission of sensitive information' query (`cpp/cleartext-transmission`) no longer raises an alert on calls to `fscanf` (and variants) when the call reads from an "obviously local" `FILE` stream such as `stdin`.

View File

@@ -1,3 +0,0 @@
## 1.6.4
No user-facing changes.

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 1.6.4 lastReleaseVersion: 1.6.1

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries name: codeql/cpp-queries
version: 1.6.5-dev version: 1.6.2-dev
groups: groups:
- cpp - cpp
- queries - queries

View File

@@ -1,2 +1 @@
query: jsf/4.13 Functions/AV Rule 107.ql jsf/4.13 Functions/AV Rule 107.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,2 +1 @@
query: Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -48,7 +48,7 @@ void test1()
void test2() void test2()
{ {
Lock<Mutex> myLock(); // BAD (interpreted as a function declaration, this does nothing) // $ Alert[cpp/function-in-block] Lock<Mutex> myLock(); // BAD (interpreted as a function declaration, this does nothing)
// ... // ...
} }
@@ -62,14 +62,14 @@ void test3()
void test4() void test4()
{ {
Lock<Mutex>(myMutex); // BAD (creates an uninitialized variable called `myMutex`, probably not intended) // $ Alert[cpp/local-variable-hides-global-variable] Lock<Mutex>(myMutex); // BAD (creates an uninitialized variable called `myMutex`, probably not intended)
// ... // ...
} }
void test5() void test5()
{ {
Lock<Mutex> myLock(Mutex); // BAD (interpreted as a function declaration, this does nothing) // $ Alert[cpp/function-in-block] Lock<Mutex> myLock(Mutex); // BAD (interpreted as a function declaration, this does nothing)
// ... // ...
} }

View File

@@ -1 +1 @@
query: semmle/code/cpp/PrintAST.ql semmle/code/cpp/PrintAST.ql

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,2 +1 @@
query: experimental/Security/CWE/CWE-020/LateCheckOfFunctionArgument.ql experimental/Security/CWE/CWE-020/LateCheckOfFunctionArgument.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

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