Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

forwarding: add a warning for public ports #192599

Merged
merged 2 commits into from
Sep 8, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 36 additions & 3 deletions extensions/tunnel-forwarding/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export async function activate(context: vscode.ExtensionContext) {
}

const logger = new Logger(vscode.l10n.t('Port Forwarding'));
const provider = new TunnelProvider(logger);
const provider = new TunnelProvider(logger, context);

context.subscriptions.push(
vscode.commands.registerCommand('tunnel-forwarding.showLog', () => logger.show()),
Expand Down Expand Up @@ -120,6 +120,8 @@ class Logger {
}
}

const didWarnPublicKey = 'didWarnPublic';

class TunnelProvider implements vscode.TunnelProvider {
private readonly tunnels = new Set<Tunnel>();
private readonly stateChange = new vscode.EventEmitter<StateT>();
Expand All @@ -136,10 +138,16 @@ class TunnelProvider implements vscode.TunnelProvider {

public readonly onDidStateChange = this.stateChange.event;

constructor(private readonly logger: Logger) { }
constructor(private readonly logger: Logger, private readonly context: vscode.ExtensionContext) { }

/** @inheritdoc */
public async provideTunnel(tunnelOptions: vscode.TunnelOptions): Promise<vscode.Tunnel> {
public async provideTunnel(tunnelOptions: vscode.TunnelOptions): Promise<vscode.Tunnel | undefined> {
if (tunnelOptions.privacy === TunnelPrivacyId.Public) {
if (!(await this.consentPublicPort(tunnelOptions.remoteAddress.port))) {
return;
}
}

const tunnel = new Tunnel(
tunnelOptions.remoteAddress,
(tunnelOptions.privacy as TunnelPrivacyId) || TunnelPrivacyId.Private,
Expand Down Expand Up @@ -184,6 +192,31 @@ class TunnelProvider implements vscode.TunnelProvider {
this.updateActivePortsIfRunning();
}

private async consentPublicPort(portNumber: number) {
const didWarn = this.context.globalState.get(didWarnPublicKey, false);
if (didWarn) {
return true;
}

const continueOpt = vscode.l10n.t('Continue');
const dontShowAgain = vscode.l10n.t("Don't show again");
const r = await vscode.window.showWarningMessage(
vscode.l10n.t("You're about to create a publicly forwarded port. Anyone on the internet will be able to connect to the service listening on port {0}. You should only proceed if this service is secure and non-sensitive.", portNumber),
{ modal: true },
continueOpt,
dontShowAgain,
);
if (r === continueOpt) {
// continue
} else if (r === dontShowAgain) {
await this.context.globalState.update(didWarnPublicKey, true);
} else {
return false;
}

return true;
}

private isInStateWithProcess(process: ChildProcessWithoutNullStreams) {
return (
(this.state.state === State.Starting || this.state.state === State.Active) &&
Expand Down