Skip to content

Commit e048a65

Browse files
authored
PR feedback
1 parent 7f58e2c commit e048a65

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

src/debugger/tunnelUrl.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,22 @@ describe("validateTunnelUrl", () => {
6161
}
6262
});
6363

64+
it("rejects URL with username", () => {
65+
const result = validateTunnelUrl("wss://user@abcdef-4711.uks1.devtunnels.ms/");
66+
expect(result.valid).toBe(false);
67+
if (!result.valid) {
68+
expect(result.reason).toContain("Credentials in tunnel URL are not allowed");
69+
}
70+
});
71+
72+
it("rejects URL with username and password", () => {
73+
const result = validateTunnelUrl("wss://user:pass@abcdef-4711.uks1.devtunnels.ms/");
74+
expect(result.valid).toBe(false);
75+
if (!result.valid) {
76+
expect(result.reason).toContain("Credentials in tunnel URL are not allowed");
77+
}
78+
});
79+
6480
it("rejects URL with just a scheme", () => {
6581
const result = validateTunnelUrl("wss://");
6682
expect(result.valid).toBe(false);

src/debugger/tunnelUrl.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,9 @@ export function validateTunnelUrl(raw: string): {valid: true; url: string} | {va
3131
return {valid: false, reason: `Host "${parsed.hostname}" is not an allowed tunnel domain`};
3232
}
3333

34+
if (parsed.username || parsed.password) {
35+
return {valid: false, reason: "Credentials in tunnel URL are not allowed"};
36+
}
37+
3438
return {valid: true, url: parsed.toString()};
3539
}

src/debugger/webSocketDapAdapter.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export class WebSocketDapAdapter implements vscode.DebugAdapter {
2525

2626
private _ws: WebSocket | undefined;
2727
private _pingTimer: ReturnType<typeof setInterval> | undefined;
28+
private _replayTimer: ReturnType<typeof setTimeout> | undefined;
29+
private _terminatedFired = false;
2830
private _disposed = false;
2931

3032
/**
@@ -143,6 +145,10 @@ export class WebSocketDapAdapter implements vscode.DebugAdapter {
143145
}
144146
this._disposed = true;
145147
this._stopPingLoop();
148+
if (this._replayTimer) {
149+
clearTimeout(this._replayTimer);
150+
this._replayTimer = undefined;
151+
}
146152
if (this._ws) {
147153
try {
148154
this._ws.close(1000, "debug session ended");
@@ -202,7 +208,9 @@ export class WebSocketDapAdapter implements vscode.DebugAdapter {
202208
const events = this._pendingStoppedEvents;
203209
this._pendingStoppedEvents = [];
204210
logDebug(`Replaying ${events.length} buffered stopped event(s)`);
205-
setTimeout(() => {
211+
this._replayTimer = setTimeout(() => {
212+
this._replayTimer = undefined;
213+
if (this._disposed) return;
206214
for (const evt of events) {
207215
this._onDidSendMessage.fire(evt);
208216
}
@@ -219,6 +227,7 @@ export class WebSocketDapAdapter implements vscode.DebugAdapter {
219227
log(`Debugger tunnel closed: ${reasonStr}`);
220228
this._stopPingLoop();
221229
this._fireTerminated();
230+
this.dispose();
222231
});
223232

224233
ws.on("error", (err: Error) => {
@@ -252,6 +261,8 @@ export class WebSocketDapAdapter implements vscode.DebugAdapter {
252261

253262
/** Notify VS Code that the debug session is over. */
254263
private _fireTerminated(): void {
264+
if (this._terminatedFired) return;
265+
this._terminatedFired = true;
255266
this._onDidSendMessage.fire({
256267
type: "event",
257268
event: "terminated",

0 commit comments

Comments
 (0)