test: codeql for wikioperation (#647)

* test: codeql for wikioperation

* test: codeql not find suite

* Move CodeQL analysis to dedicated workflow

Extracted the CodeQL security analysis job from test.yml into a new codeql-analysis.yml workflow file for better separation of concerns and maintainability.

* Update codeql-analysis.yml

* de

* 。
This commit is contained in:
lin onetwo 2025-10-24 16:40:32 +08:00 committed by GitHub
parent 47a0c93cfe
commit 6700c62243
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 358 additions and 15 deletions

18
.github/codeql/codeql-config.yml vendored Normal file
View file

@ -0,0 +1,18 @@
name: "TidGi CodeQL Security Analysis"
queries:
- uses: security-extended
# Paths to analyze (only source code)
paths:
- src
- scripts
# Paths to ignore within the analyzed paths
# (Excludes test files and mock data from security analysis)
paths-ignore:
- '**/__tests__/**'
- '**/__mocks__/**'
- '**/*.test.ts'
- '**/*.test.tsx'
- '**/*.spec.ts'

30
.github/codeql/codeql-pack.lock.yml vendored Normal file
View file

@ -0,0 +1,30 @@
---
lockVersion: 1.0.0
dependencies:
codeql/concepts:
version: 0.0.7
codeql/controlflow:
version: 2.0.17
codeql/dataflow:
version: 2.0.17
codeql/javascript-all:
version: 2.6.13
codeql/mad:
version: 1.0.33
codeql/regex:
version: 1.0.33
codeql/ssa:
version: 2.0.9
codeql/threat-models:
version: 1.0.33
codeql/tutorial:
version: 1.0.33
codeql/typetracking:
version: 2.0.17
codeql/util:
version: 2.0.20
codeql/xml:
version: 1.0.33
codeql/yaml:
version: 1.0.33
compiled: false

View file

@ -0,0 +1,83 @@
/**
* @name Unsafe use of webFrame.executeJavaScript with user input
* @description Detects Electron webFrame.executeJavaScript calls with potentially tainted template strings
* @kind path-problem
* @problem.severity error
* @security-severity 9.0
* @precision high
* @id tidgi/electron-execute-javascript-injection
* @tags security
* electron
* external/cwe/cwe-094
*/
import javascript
import DataFlow::PathGraph
/**
* A call to webFrame.executeJavaScript
*/
class ExecuteJavaScriptCall extends DataFlow::MethodCallNode {
ExecuteJavaScriptCall() {
this.getMethodName() = "executeJavaScript" and
(
this.getReceiver().(DataFlow::PropRead).getPropertyName() = "webFrame" or
this.getReceiver().asExpr().(Identifier).getName() = "webFrame"
)
}
}
/**
* Configuration for tracking unsafe executeJavaScript usage
*/
class ExecuteJavaScriptInjectionConfig extends TaintTracking::Configuration {
ExecuteJavaScriptInjectionConfig() {
this = "ExecuteJavaScriptInjectionConfig"
}
override predicate isSource(DataFlow::Node source) {
// Function parameters
source.asExpr() instanceof Parameter or
// Object property access
source instanceof DataFlow::PropRead or
// Deep link handlers
exists(DataFlow::CallNode call |
(call.getCalleeName() = "on" or call.getCalleeName() = "handle") and
call.getArgument(0).getStringValue() = ["open-url", "second-instance"] and
source = call.getCallback(1).getParameter([0..2])
)
}
override predicate isSink(DataFlow::Node sink) {
exists(ExecuteJavaScriptCall exec |
sink = exec.getArgument(0)
)
}
override predicate isSanitizer(DataFlow::Node node) {
// JSON.stringify sanitizes the input
exists(DataFlow::CallNode call |
call = DataFlow::globalVarRef("JSON").getAMemberCall("stringify") and
node = call
) or
// Explicit type checks
exists(DataFlow::CallNode call |
call.getCalleeName() = ["isString", "isNumber", "isBoolean"] and
node = call
)
}
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
// Template string interpolation is a taint step
exists(TemplateLiteral tl |
pred.asExpr() = tl.getAnElement() and
succ.asExpr() = tl
)
}
}
from ExecuteJavaScriptInjectionConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink,
"Potential code injection in webFrame.executeJavaScript: user input $@ flows into executed code without proper sanitization",
source.getNode(), "here"

View file

@ -0,0 +1,83 @@
/**
* @name Unsafe use of Function constructor with user input
* @description Detects Function constructor calls with potentially tainted template strings
* @kind path-problem
* @problem.severity error
* @security-severity 9.0
* @precision high
* @id tidgi/new-function-injection
* @tags security
* external/cwe/cwe-094
*/
import javascript
import DataFlow::PathGraph
/**
* A call to the Function constructor
*/
class FunctionConstructorCall extends DataFlow::NewNode {
FunctionConstructorCall() {
this.getCalleeName() = "Function"
}
}
/**
* Configuration for tracking unsafe Function constructor usage
*/
class FunctionConstructorInjectionConfig extends TaintTracking::Configuration {
FunctionConstructorInjectionConfig() {
this = "FunctionConstructorInjectionConfig"
}
override predicate isSource(DataFlow::Node source) {
// Function parameters
source.asExpr() instanceof Parameter or
// Object property access
source instanceof DataFlow::PropRead or
// IPC message handlers
exists(DataFlow::CallNode call |
(call.getCalleeName() = "on" or call.getCalleeName() = "handle") and
source = call.getCallback([0..1]).getParameter([0..2])
)
}
override predicate isSink(DataFlow::Node sink) {
exists(FunctionConstructorCall fnCall |
sink = fnCall.getAnArgument()
)
}
override predicate isSanitizer(DataFlow::Node node) {
// JSON.parse/stringify are safe
exists(DataFlow::CallNode call |
call = DataFlow::globalVarRef("JSON").getAMemberCall(["stringify", "parse"]) and
node = call
) or
// Whitelist validation
exists(DataFlow::MethodCallNode test |
test.getMethodName() = "test" and
test.getReceiver().asExpr() instanceof RegExpLiteral and
node = test
)
}
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
// Template string interpolation
exists(TemplateLiteral tl |
pred.asExpr() = tl.getAnElement() and
succ.asExpr() = tl
) or
// String concatenation
exists(AddExpr add |
pred.asExpr() = add.getAnOperand() and
succ.asExpr() = add
)
}
}
from FunctionConstructorInjectionConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink,
"Potential code injection via Function constructor: user input $@ flows into dynamically created function",
source.getNode(), "here"

4
.github/codeql/qlpack.yml vendored Normal file
View file

@ -0,0 +1,4 @@
name: tidgi/security-queries
version: 1.0.0
dependencies:
codeql/javascript-all: "*"

View file

@ -0,0 +1,96 @@
/**
* @name Template string injection in code execution
* @description Detects user input flowing into template strings that are passed to code execution functions
* @kind path-problem
* @problem.severity error
* @security-severity 9.3
* @precision high
* @id tidgi/template-string-injection
* @tags security
* external/cwe/cwe-094
* external/cwe/cwe-095
*/
import javascript
import DataFlow::PathGraph
/**
* A call to a function that executes code dynamically
*/
class CodeExecutionCall extends DataFlow::CallNode {
CodeExecutionCall() {
// Direct code execution
this.getCalleeName() = ["eval", "Function"] or
// Electron-specific code execution
this.getCalleeName() = "executeJavaScript" or
// VM module code execution
this.(DataFlow::MethodCallNode).getMethodName() = ["runInContext", "runInNewContext", "runInThisContext"]
}
}
/**
* A template literal that contains potentially tainted elements
*/
class TaintedTemplateLiteral extends DataFlow::Node {
TemplateLiteral literal;
TaintedTemplateLiteral() {
this.asExpr() = literal
}
TemplateLiteral getLiteral() {
result = literal
}
}
/**
* Configuration for tracking tainted data flow into template literals used in code execution
*/
class TemplateStringInjectionConfig extends TaintTracking::Configuration {
TemplateStringInjectionConfig() {
this = "TemplateStringInjectionConfig"
}
override predicate isSource(DataFlow::Node source) {
// Any parameter or property access could be user-controlled
source.asExpr() instanceof Parameter or
source instanceof DataFlow::PropRead or
// IPC sources in Electron
exists(DataFlow::CallNode call |
call.getCalleeName() = ["on", "handle", "once"] and
source = call.getCallback(0).getParameter(1)
)
}
override predicate isSink(DataFlow::Node sink) {
// Template literal elements that flow into code execution
exists(CodeExecutionCall exec, TaintedTemplateLiteral tl |
exec.getAnArgument() = tl and
exists(Expr element |
element = tl.getLiteral().getAnElement() and
sink.asExpr() = element
)
)
}
override predicate isSanitizer(DataFlow::Node node) {
// JSON.stringify is a safe sanitizer
exists(DataFlow::CallNode call |
call = DataFlow::globalVarRef("JSON").getAMemberCall("stringify") and
node = call
)
}
}
from TemplateStringInjectionConfig config, DataFlow::PathNode source, DataFlow::PathNode sink,
CodeExecutionCall exec, TaintedTemplateLiteral tl
where
config.hasFlowPath(source, sink) and
exec.getAnArgument() = tl and
exists(Expr element |
element = tl.getLiteral().getAnElement() and
sink.getNode().asExpr() = element
)
select exec, source, sink,
"Potential code injection: user input $@ flows into template string passed to " + exec.getCalleeName(),
source.getNode(), "here"

42
.github/workflows/codeql-analysis.yml vendored Normal file
View file

@ -0,0 +1,42 @@
name: "CodeQL Security Analysis"
on:
push:
tags:
- "v*.*.*"
paths-ignore:
- "README.md"
- "docs/**"
- ".vscode"
pull_request:
branches:
- master
paths-ignore:
- "docs/**"
- "README.md"
- ".vscode"
jobs:
analyze:
name: Analyze JavaScript/TypeScript
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-config.yml
queries: +./.github/codeql
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:javascript-typescript"

View file

@ -59,17 +59,3 @@ jobs:
userData-test/settings/
retention-days: 7
continue-on-error: true
codeql:
name: CodeQL Analysis
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript-typescript
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3

3
.gitignore vendored
View file

@ -72,4 +72,5 @@ userData-test/
wiki-dev/
wiki-test/
*.tsbuildinfo
tsconfig.test.json.tsbuildinfo
tsconfig.test.json.tsbuildinfo
/tidgi-codeql-db