Skip to content

Commit 573ad8d

Browse files
committed
[WIP] test codeql and code coverage
Signed-off-by: Davanum Srinivas <[email protected]>
1 parent 0478308 commit 573ad8d

File tree

4 files changed

+395
-3
lines changed

4 files changed

+395
-3
lines changed

.github/workflows/code-scanning.yml

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ jobs:
3232
prepare-environment:
3333
uses: ./.github/workflows/prepare-environment.yml
3434

35-
analyze:
36-
name: Analyze Go code with CodeQL
35+
codeql-pr-analysis:
36+
if: startsWith(github.ref, 'refs/heads/pull-request/')
37+
name: CodeQL PR Analysis
3738
runs-on: linux-amd64-cpu4
3839
timeout-minutes: 360
3940
needs: prepare-environment
@@ -63,9 +64,53 @@ jobs:
6364
build-mode: manual
6465
env:
6566
CODEQL_EXTRACTOR_GO_BUILD_TRACING: on
66-
- shell: bash
67+
68+
- name: Build with CodeQL
6769
run: |
6870
make build-all
71+
72+
- name: Perform CodeQL Analysis
73+
uses: github/codeql-action/analyze@v3
74+
with:
75+
category: "/language:go"
76+
77+
codeql-baseline-analysis:
78+
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
79+
name: CodeQL Baseline Analysis
80+
runs-on: linux-amd64-cpu4
81+
timeout-minutes: 360
82+
needs: prepare-environment
83+
permissions:
84+
security-events: write
85+
packages: read
86+
steps:
87+
- name: Checkout repository
88+
uses: actions/checkout@v4
89+
90+
- name: Setup build environment
91+
uses: ./.github/actions/setup-build-env
92+
with:
93+
go-version: ${{ needs.prepare-environment.outputs.go_version }}
94+
python-version: ${{ needs.prepare-environment.outputs.python_version }}
95+
poetry-version: ${{ needs.prepare-environment.outputs.poetry_version }}
96+
golangci-lint-version: ${{ needs.prepare-environment.outputs.golangci_lint_version }}
97+
protobuf-version: ${{ needs.prepare-environment.outputs.protobuf_version }}
98+
protoc-gen-go-version: ${{ needs.prepare-environment.outputs.protoc_gen_go_version }}
99+
protoc-gen-go-grpc-version: ${{ needs.prepare-environment.outputs.protoc_gen_go_grpc_version }}
100+
shellcheck-version: ${{ needs.prepare-environment.outputs.shellcheck_version }}
101+
102+
- name: Initialize CodeQL
103+
uses: github/codeql-action/init@v3
104+
with:
105+
languages: go
106+
build-mode: manual
107+
env:
108+
CODEQL_EXTRACTOR_GO_BUILD_TRACING: on
109+
110+
- name: Build with CodeQL
111+
run: |
112+
make build-all
113+
69114
- name: Perform CodeQL Analysis
70115
uses: github/codeql-action/analyze@v3
71116
with:

.github/workflows/lint-test.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,24 @@ jobs:
212212
path: consolidated-coverage/coverage.txt
213213
retention-days: 30
214214

215+
- name: Extract PR number from branch name
216+
id: pr-number
217+
run: |
218+
if [[ "${{ github.ref }}" =~ pull-request/([0-9]+) ]]; then
219+
echo "pr_number=${BASH_REMATCH[1]}" >> $GITHUB_OUTPUT
220+
else
221+
echo "pr_number=" >> $GITHUB_OUTPUT
222+
fi
223+
215224
- name: Generate Go Coverage Report
216225
uses: fgrosse/go-coverage-report@8c1d1a09864211d258937b1b1a5b849f7e4f2682 # v1.2.0
217226
with:
218227
coverage-artifact-name: "consolidated-code-coverage"
219228
coverage-file-name: "coverage.txt"
220229
root-package: "github.com/NVIDIA/nvsentinel"
221230
skip-comment: false
231+
env:
232+
GITHUB_PR_NUMBER: ${{ steps.pr-number.outputs.pr_number }}
222233
continue-on-error: true # Don't fail if baseline coverage doesn't exist yet
223234

224235
consolidated-coverage-baseline:
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
// Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package pkg
16+
17+
import (
18+
"context"
19+
"database/sql"
20+
"fmt"
21+
"net/http"
22+
"os/exec"
23+
"time"
24+
25+
"go.mongodb.org/mongo-driver/bson"
26+
"go.mongodb.org/mongo-driver/mongo"
27+
"go.mongodb.org/mongo-driver/mongo/options"
28+
)
29+
30+
// TestService contains intentional security vulnerabilities for CodeQL testing
31+
// DO NOT USE IN PRODUCTION
32+
type TestService struct{}
33+
34+
// NewTestService creates a new test service with vulnerabilities
35+
func NewTestService() *TestService {
36+
return &TestService{}
37+
}
38+
39+
// VulnerableMongoQuery demonstrates NoSQL injection vulnerability
40+
func (ts *TestService) VulnerableMongoQuery(userInput string) ([]bson.M, error) {
41+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
42+
defer cancel()
43+
44+
// Connect to MongoDB
45+
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
46+
if err != nil {
47+
return nil, err
48+
}
49+
50+
defer func() {
51+
_ = client.Disconnect(ctx)
52+
}()
53+
54+
collection := client.Database("testdb").Collection("users")
55+
56+
// NoSQL Injection vulnerability - user input directly used in query
57+
// This allows attackers to inject malicious queries
58+
filter := bson.M{"name": userInput}
59+
if userInput == "admin" {
60+
// Even worse - eval-like behavior
61+
filter = bson.M{"$where": "this.name == '" + userInput + "'"}
62+
}
63+
64+
cursor, err := collection.Find(ctx, filter)
65+
if err != nil {
66+
return nil, err
67+
}
68+
defer cursor.Close(ctx)
69+
70+
var results []bson.M
71+
if err = cursor.All(ctx, &results); err != nil {
72+
return nil, err
73+
}
74+
75+
return results, nil
76+
}
77+
78+
// VulnerableCommandExecution demonstrates command injection vulnerability
79+
func (ts *TestService) VulnerableCommandExecution(filename string) (string, error) {
80+
// VULNERABLE: Direct command injection - this should trigger CWE-078
81+
cmd := exec.Command("bash", "-c", filename) // User input directly as shell command
82+
output, err := cmd.Output()
83+
84+
if err != nil {
85+
return "", err
86+
}
87+
88+
return string(output), nil
89+
}
90+
91+
// UnsafePathConstruction demonstrates path traversal vulnerability
92+
func (ts *TestService) UnsafePathConstruction(userPath string) string {
93+
// Path traversal vulnerability - allows ../../../etc/passwd
94+
basePath := "/safe/directory/"
95+
unsafePath := basePath + userPath // No validation or sanitization
96+
97+
return unsafePath
98+
}
99+
100+
// WeakRandom demonstrates weak random number generation
101+
func (ts *TestService) WeakRandom() int {
102+
// This will trigger CodeQL's weak randomness detection
103+
// math/rand without crypto/rand for security purposes
104+
return 42 // Intentionally predictable for testing
105+
}
106+
107+
// CoveredFunction is a simple function to ensure code coverage
108+
func (ts *TestService) CoveredFunction(input string) string {
109+
if input == "" {
110+
return "empty"
111+
}
112+
113+
if len(input) > 10 {
114+
return "long"
115+
}
116+
117+
return fmt.Sprintf("processed: %s", input)
118+
}
119+
120+
// MultipleBranches creates multiple code paths for coverage testing
121+
func (ts *TestService) MultipleBranches(value int) string {
122+
switch {
123+
case value < 0:
124+
return "negative"
125+
case value == 0:
126+
return "zero"
127+
case value < 10:
128+
return "small"
129+
case value < 100:
130+
return "medium"
131+
default:
132+
return "large"
133+
}
134+
}
135+
136+
// VulnerableHTTPHandler demonstrates multiple vulnerabilities in HTTP context
137+
// This creates clear data flow paths that CodeQL can track
138+
func (ts *TestService) VulnerableHTTPHandler(w http.ResponseWriter, r *http.Request) {
139+
// Get user input from query parameters
140+
userInput := r.URL.Query().Get("input")
141+
command := r.URL.Query().Get("cmd")
142+
filename := r.URL.Query().Get("file")
143+
144+
// SQL Injection via string concatenation
145+
if userInput != "" {
146+
// VULNERABLE: Direct string concatenation in query
147+
queryString := "SELECT * FROM users WHERE name = '" + userInput + "'"
148+
_, _ = w.Write([]byte("Query: " + queryString + "\n"))
149+
}
150+
151+
// Command Injection
152+
if command != "" {
153+
// VULNERABLE: User input directly in shell command
154+
cmd := exec.Command("sh", "-c", command)
155+
output, _ := cmd.Output()
156+
_, _ = w.Write([]byte("Command output: " + string(output) + "\n"))
157+
}
158+
159+
// Path Traversal
160+
if filename != "" {
161+
// VULNERABLE: No path validation
162+
unsafePath := "/app/files/" + filename
163+
cmd := exec.Command("cat", unsafePath)
164+
output, _ := cmd.Output()
165+
_, _ = w.Write([]byte("File content: " + string(output) + "\n"))
166+
}
167+
168+
// Call other vulnerable functions to create call graph
169+
_, _ = ts.VulnerableCommandExecution(filename)
170+
_ = ts.UnsafePathConstruction(userInput)
171+
}
172+
173+
// VulnerableSQLQuery demonstrates classic SQL injection
174+
func (ts *TestService) VulnerableSQLQuery(db *sql.DB, userID string) error {
175+
// VULNERABLE: Direct string concatenation in SQL query
176+
//nolint:gosec // G202: Intentional SQL injection for testing
177+
query := "SELECT * FROM users WHERE id = " + userID
178+
_, err := db.Query(query)
179+
180+
return err
181+
}
182+
183+
// AnotherVulnerableSQLQuery with string formatting
184+
func (ts *TestService) AnotherVulnerableSQLQuery(db *sql.DB, username string) error {
185+
// VULNERABLE: String formatting in SQL query
186+
//nolint:gosec // G201: Intentional SQL injection for testing
187+
query := fmt.Sprintf("SELECT * FROM users WHERE username = '%s'", username)
188+
_, err := db.Query(query)
189+
190+
return err
191+
}

0 commit comments

Comments
 (0)