Skip to content

Commit be955bb

Browse files
committed
feat: Add threat model configuration and UI support for CodeQL analysis
1 parent 93fbf49 commit be955bb

File tree

2 files changed

+101
-10
lines changed

2 files changed

+101
-10
lines changed

src/providers/uiProvider.ts

Lines changed: 95 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ export class UiProvider implements vscode.WebviewViewProvider {
117117
config.codeqlPath,
118118
vscode.ConfigurationTarget.Global
119119
),
120+
workspaceConfig.update(
121+
"threatModel",
122+
config.threatModel,
123+
vscode.ConfigurationTarget.Workspace
124+
),
120125
]);
121126

122127
this.logger.logServiceCall(
@@ -156,16 +161,30 @@ export class UiProvider implements vscode.WebviewViewProvider {
156161
private async loadConfiguration() {
157162
const config = vscode.workspace.getConfiguration("codeql-scanner");
158163

164+
// Check if threatModel is set, if not automatically set it to "Remote"
165+
let threatModel = config.get<string>("threatModel");
166+
if (!threatModel) {
167+
threatModel = "Remote";
168+
// Automatically save the default threat model to configuration
169+
await config.update(
170+
"threatModel",
171+
threatModel,
172+
vscode.ConfigurationTarget.Workspace
173+
);
174+
this.logger.info(
175+
"UiProvider",
176+
"Automatically set threat model to 'Remote' as default"
177+
);
178+
}
179+
159180
const configuration = {
160181
githubToken: config.get<string>("github.token", ""),
161182
githubOwner: config.get<string>("github.owner", ""),
162183
githubRepo: config.get<string>("github.repo", ""),
163-
suites: config.get<string[]>("suites", [
164-
"security-extended",
165-
"security-and-quality",
166-
]),
184+
suites: config.get<string[]>("suites", ["code-scanning"]),
167185
languages: config.get<string[]>("languages", []),
168186
codeqlPath: config.get<string>("codeqlPath", "codeql"),
187+
threatModel: threatModel,
169188
};
170189

171190
this._view?.webview.postMessage({
@@ -1048,7 +1067,17 @@ export class UiProvider implements vscode.WebviewViewProvider {
10481067
}
10491068
10501069
.suite-radio input[type="radio"]:checked + label .suite-name {
1051-
color: var(--vscode-focusBorder);
1070+
color: #28a745;
1071+
}
1072+
1073+
.suite-radio:has(input[type="radio"]:checked) {
1074+
background-color: rgba(40, 167, 69, 0.1);
1075+
border-color: #28a745;
1076+
}
1077+
1078+
.suite-radio:has(input[type="radio"]:checked):hover {
1079+
background-color: rgba(40, 167, 69, 0.15);
1080+
border-color: #28a745;
10521081
}
10531082
</style>
10541083
</head>
@@ -1146,6 +1175,27 @@ export class UiProvider implements vscode.WebviewViewProvider {
11461175
</div>
11471176
<div class="help-text">Select the CodeQL query suite to run during analysis</div>
11481177
</div>
1178+
1179+
<div class="form-group">
1180+
<label for="threatModel">Threat Model:</label>
1181+
<div id="threatModelContainer">
1182+
<div class="suite-radio">
1183+
<input type="radio" id="threat-remote" name="threatModel" value="Remote">
1184+
<label for="threat-remote">
1185+
<span class="suite-name">Remote</span>
1186+
<span class="suite-description">Analyze threats from external attackers and remote code execution</span>
1187+
</label>
1188+
</div>
1189+
<div class="suite-radio">
1190+
<input type="radio" id="threat-local" name="threatModel" value="Local">
1191+
<label for="threat-local">
1192+
<span class="suite-name">Local</span>
1193+
<span class="suite-description">Focus on local threats and privilege escalation scenarios</span>
1194+
</label>
1195+
</div>
1196+
</div>
1197+
<div class="help-text">Select the threat model to focus the analysis on specific security scenarios</div>
1198+
</div>
11491199
</div>
11501200
<div class="section">
11511201
<h3>Langauge Selection</h3>
@@ -1178,7 +1228,8 @@ export class UiProvider implements vscode.WebviewViewProvider {
11781228
githubRepo: document.getElementById('githubRepo').value,
11791229
suites: [getSelectedSuite()],
11801230
languages: getSelectedLanguages(),
1181-
codeqlPath: document.getElementById('codeqlPath').value
1231+
codeqlPath: document.getElementById('codeqlPath').value,
1232+
threatModel: getSelectedThreatModel()
11821233
};
11831234
11841235
vscode.postMessage({
@@ -1198,7 +1249,23 @@ export class UiProvider implements vscode.WebviewViewProvider {
11981249
radioButton.checked = true;
11991250
} else {
12001251
// Default to code-scanning if suite not found
1201-
const defaultRadio = document.querySelector('input[name="suite"][value="code-scanningd"]');
1252+
const defaultRadio = document.querySelector('input[name="suite"][value="code-scanning"]');
1253+
if (defaultRadio) defaultRadio.checked = true;
1254+
}
1255+
}
1256+
1257+
function getSelectedThreatModel() {
1258+
const selectedRadio = document.querySelector('input[name="threatModel"]:checked');
1259+
return selectedRadio ? selectedRadio.value : 'Remote';
1260+
}
1261+
1262+
function setSelectedThreatModel(threatModel) {
1263+
const radioButton = document.querySelector('input[name="threatModel"][value="' + threatModel + '"]');
1264+
if (radioButton) {
1265+
radioButton.checked = true;
1266+
} else {
1267+
// Default to Remote if threat model not found
1268+
const defaultRadio = document.querySelector('input[name="threatModel"][value="Remote"]');
12021269
if (defaultRadio) defaultRadio.checked = true;
12031270
}
12041271
}
@@ -1432,12 +1499,16 @@ export class UiProvider implements vscode.WebviewViewProvider {
14321499
document.getElementById('githubOwner').value = config.githubOwner || '';
14331500
document.getElementById('githubRepo').value = config.githubRepo || '';
14341501
1435-
// Set selected suite (take first suite if multiple, default to security-extended)
1436-
const selectedSuite = config.suites && config.suites.length > 0 ? config.suites[0] : 'security-extended';
1502+
// Set selected suite (take first suite if multiple, default to code-scanning)
1503+
const selectedSuite = config.suites && config.suites.length > 0 ? config.suites[0] : 'code-scanning';
14371504
setSelectedSuite(selectedSuite);
14381505
14391506
document.getElementById('codeqlPath').value = config.codeqlPath || 'codeql';
14401507
1508+
// Set selected threat model (default to Remote)
1509+
const selectedThreatModel = config.threatModel || 'Remote';
1510+
setSelectedThreatModel(selectedThreatModel);
1511+
14411512
// Set selected languages if available
14421513
if (config.languages && config.languages.length > 0) {
14431514
setSelectedLanguages(config.languages);
@@ -1518,6 +1589,21 @@ export class UiProvider implements vscode.WebviewViewProvider {
15181589
// Load configuration on startup
15191590
loadConfig();
15201591
1592+
// Initialize defaults if nothing is selected
1593+
setTimeout(() => {
1594+
// Ensure a suite is always selected
1595+
if (!document.querySelector('input[name="suite"]:checked')) {
1596+
const defaultSuite = document.querySelector('input[name="suite"][value="code-scanning"]');
1597+
if (defaultSuite) defaultSuite.checked = true;
1598+
}
1599+
1600+
// Ensure a threat model is always selected
1601+
if (!document.querySelector('input[name="threatModel"]:checked')) {
1602+
const defaultThreatModel = document.querySelector('input[name="threatModel"][value="Remote"]');
1603+
if (defaultThreatModel) defaultThreatModel.checked = true;
1604+
}
1605+
}, 100);
1606+
15211607
// Load alerts summary
15221608
vscode.postMessage({ command: 'loadAlertsSummary' });
15231609
</script>

src/services/codeqlService.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,7 @@ export class CodeQLService {
784784
const config = vscode.workspace.getConfiguration("codeql-scanner");
785785
const codeqlPath = config.get<string>("codeqlPath", "codeql");
786786
const suite = config.get<string>("suite", "code-scanning");
787+
const threatModel = config.get<string>("threatModel", "Remote").toLowerCase();
787788

788789
const outputPath = path.join(
789790
codeqlDir,
@@ -801,7 +802,11 @@ export class CodeQLService {
801802
queries += `:codeql-suites/${language}-code-scanning.qls`;
802803
}
803804

804-
const command = `${codeqlPath} database analyze --output "${outputPath}" --format sarif-latest "${databasePath}" "${queries}"`;
805+
var command = `${codeqlPath} database analyze --output "${outputPath}" --format sarif-latest`;
806+
if (threatModel !== "remote") {
807+
command += ` --threat-model ${threatModel}`;
808+
}
809+
command += ` "${databasePath}" "${queries}"`;
805810

806811
try {
807812
progress.report({ message: "Running CodeQL analysis..." });

0 commit comments

Comments
 (0)