Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/hoverAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class JavaHoverProvider implements HoverProvider {
}

const contributed = new MarkdownString(contributedCommands.map((command) => this.convertCommandToMarkdown(command)).join(' | '));
contributed.isTrusted = true;
contributed.isTrusted = { enabledCommands: contributedCommands.map((command) => command.command) };
let contents: MarkdownString[] = [ contributed ];
let range;
if (serverHover && serverHover.contents) {
Expand Down
8 changes: 7 additions & 1 deletion src/providerDispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,13 @@ export function fixJdtSchemeHoverLinks(hover: Hover): Hover {
const newContents: (MarkedString | MarkdownString)[] = [];
for (const content of hover.contents) {
if (content instanceof MarkdownString) {
newContents.push(fixJdtLinksInDocumentation(content));
// Skip our own trusted contributed commands (e.g. "Go to Super Implementation");
// only sanitize untrusted server-provided Javadoc.
if (content.isTrusted) {
newContents.push(content);
} else {
newContents.push(fixJdtLinksInDocumentation(content));
}
} else {
newContents.push(content);
}
Expand Down
37 changes: 37 additions & 0 deletions test/standard-mode-suite/hoverLinks.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict';

import * as assert from 'assert';
import { Hover, MarkdownString } from 'vscode';
import { fixJdtSchemeHoverLinks } from '../../src/providerDispatcher';

suite('Hover Links Test', () => {

test('trusted contributed command links are preserved (super implementation)', () => {
const contributed = new MarkdownString('[Go to Super Implementation](command:java.action.navigateToSuperImplementation?%5B%5D)');
contributed.isTrusted = { enabledCommands: ['java.action.navigateToSuperImplementation'] };
const hover = new Hover([contributed]);

const fixed = fixJdtSchemeHoverLinks(hover);
const value = (fixed.contents[0] as MarkdownString).value;
assert.ok(value.includes('(command:java.action.navigateToSuperImplementation'), 'contributed command link should not be sanitized');
});

test('untrusted server command links are sanitized', () => {
const javadoc = new MarkdownString('[click here](command:evil.command?param=true)');
const hover = new Hover([javadoc]);

const fixed = fixJdtSchemeHoverLinks(hover);
const value = (fixed.contents[0] as MarkdownString).value;
assert.strictEqual(value, 'click here', 'server command link should be stripped to its label');
});

test('jdt:// links are converted to command links', () => {
const javadoc = new MarkdownString('[String](jdt://contents/Foo.class)');
const hover = new Hover([javadoc]);

const fixed = fixJdtSchemeHoverLinks(hover);
const value = (fixed.contents[0] as MarkdownString).value;
assert.ok(value.includes('(command:'), 'jdt link should be converted to a command link');
assert.ok(!value.includes('jdt://'), 'jdt scheme should be replaced');
});
});
Loading