Skip to content

Commit db3b757

Browse files
Merge pull request #7302 from continuedev/dallin/prevent-unsafe-file-reads
feat: prevent unsafe file reads
2 parents da3f07f + 41dfda6 commit db3b757

File tree

28 files changed

+744
-77
lines changed

28 files changed

+744
-77
lines changed

.github/workflows/cli-pr-checks.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ jobs:
2525
cache: "npm"
2626
cache-dependency-path: extensions/cli/package-lock.json
2727

28+
- name: Setup packages
29+
uses: ./.github/actions/setup-packages
30+
- name: Setup core component
31+
uses: ./.github/actions/setup-component
32+
with:
33+
component: core
34+
include-root: true
35+
2836
- name: Install dependencies
2937
run: |
3038
cd extensions/cli
@@ -53,6 +61,14 @@ jobs:
5361
cache: "npm"
5462
cache-dependency-path: extensions/cli/package-lock.json
5563

64+
- name: Setup packages
65+
uses: ./.github/actions/setup-packages
66+
- name: Setup core component
67+
uses: ./.github/actions/setup-component
68+
with:
69+
component: core
70+
include-root: true
71+
5672
- name: Install dependencies
5773
run: |
5874
cd extensions/cli

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
"extensions/vscode/e2e/_output": true,
4343
"extensions/vscode/e2e/storage": true,
4444
"extensions/vscode/e2e/vsix": true,
45-
"extensions/.continue-debug": true
45+
"extensions/.continue-debug": true,
46+
"extensions/cli/dist/**": true
4647
// "sync/**": true
4748
},
4849
"editor.formatOnSave": true,

binary/package-lock.json

Lines changed: 12 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/autocomplete/CompletionProvider.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ import { DEFAULT_AUTOCOMPLETE_OPTS } from "../util/parameters.js";
66
import { shouldCompleteMultiline } from "./classification/shouldCompleteMultiline.js";
77
import { ContextRetrievalService } from "./context/ContextRetrievalService.js";
88

9+
import { isSecurityConcern } from "../indexing/ignore.js";
910
import { BracketMatchingService } from "./filtering/BracketMatchingService.js";
1011
import { CompletionStreamer } from "./generation/CompletionStreamer.js";
1112
import { postprocessCompletion } from "./postprocessing/index.js";
1213
import { shouldPrefilter } from "./prefiltering/index.js";
13-
import { renderPromptWithTokenLimit } from "./templating/index.js";
1414
import { getAllSnippetsWithoutRace } from "./snippets/index.js";
15+
import { renderPromptWithTokenLimit } from "./templating/index.js";
1516
import { GetLspDefinitionsFunction } from "./types.js";
1617
import { AutocompleteDebouncer } from "./util/AutocompleteDebouncer.js";
1718
import { AutocompleteLoggingService } from "./util/AutocompleteLoggingService.js";
@@ -150,6 +151,10 @@ export class CompletionProvider {
150151
return undefined;
151152
}
152153

154+
if (isSecurityConcern(input.filepath)) {
155+
return undefined;
156+
}
157+
153158
const options = await this._getAutocompleteOptions(llm);
154159

155160
// Debounce

core/autocomplete/prefiltering/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { IDE } from "../..";
44
import {
55
getGlobalContinueIgArray,
66
getWorkspaceContinueIgArray,
7-
} from "../../indexing/ignore";
7+
} from "../../indexing/continueignore";
88
import { getConfigJsonPath } from "../../util/paths";
99
import { findUriInDirs } from "../../util/uri";
1010
import { HelperVars } from "../util/HelperVars";

core/commands/slash/built-in-legacy/onboard.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import ignore from "ignore";
22

33
import type { FileType, IDE, SlashCommand } from "../../..";
4-
import {
5-
DEFAULT_IGNORE,
6-
getGlobalContinueIgArray,
7-
gitIgArrayFromFile,
8-
} from "../../../indexing/ignore";
4+
import { getGlobalContinueIgArray } from "../../../indexing/continueignore";
5+
import { DEFAULT_IGNORE, gitIgArrayFromFile } from "../../../indexing/ignore";
96
import { renderChatMessage } from "../../../util/messageContent";
107
import {
118
findUriInDirs,

core/context/providers/FileContextProvider.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
ContextSubmenuItem,
77
LoadSubmenuItemsArgs,
88
} from "../../";
9+
import { isSecurityConcern } from "../../indexing/ignore";
910
import { walkDirs } from "../../indexing/walkDir";
1011
import {
1112
getShortestUniqueRelativeUriPaths,
@@ -36,6 +37,21 @@ class FileContextProvider extends BaseContextProvider {
3637
await extras.ide.getWorkspaceDirs(),
3738
);
3839

40+
if (isSecurityConcern(relativePathOrBasename)) {
41+
return [
42+
{
43+
description: last2Parts,
44+
content:
45+
"Content redacted, this file cannot be viewed for security reasons",
46+
name: baseName,
47+
uri: {
48+
type: "file",
49+
value: fileUri,
50+
},
51+
},
52+
];
53+
}
54+
3955
return [
4056
{
4157
name: baseName,

core/context/providers/OpenFilesContextProvider.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
ContextProviderDescription,
44
ContextProviderExtras,
55
} from "../../index.js";
6+
import { isSecurityConcern } from "../../indexing/ignore.js";
67
import { getUriDescription } from "../../util/uri.js";
78
import { BaseContextProvider } from "../index.js";
89

@@ -27,10 +28,23 @@ class OpenFilesContextProvider extends BaseContextProvider {
2728

2829
return await Promise.all(
2930
openFiles.map(async (filepath: string) => {
30-
const content = await ide.readFile(filepath);
3131
const { relativePathOrBasename, last2Parts, baseName } =
3232
getUriDescription(filepath, workspaceDirs);
3333

34+
if (isSecurityConcern(filepath)) {
35+
return {
36+
description: last2Parts,
37+
content:
38+
"Content redacted, this file cannot be viewed for security reasons",
39+
name: baseName,
40+
uri: {
41+
type: "file",
42+
value: filepath,
43+
},
44+
};
45+
}
46+
const content = await ide.readFile(filepath);
47+
3448
return {
3549
description: last2Parts,
3650
content: `\`\`\`${relativePathOrBasename}\n${content}\n\`\`\``,

core/context/providers/ProblemsContextProvider.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
ContextProviderDescription,
44
ContextProviderExtras,
55
} from "../../index.js";
6+
import { isSecurityConcern } from "../../indexing/ignore.js";
67
import { getUriDescription } from "../../util/uri.js";
78
import { BaseContextProvider } from "../index.js";
89

@@ -28,6 +29,14 @@ class ProblemsContextProvider extends BaseContextProvider {
2829
problem.filepath,
2930
workspaceDirs,
3031
);
32+
if (isSecurityConcern(relativePathOrBasename)) {
33+
return {
34+
description: "Problems in current file",
35+
content:
36+
"Content was redacted because the file is detected as a potential security concern",
37+
name: `Warnings in ${baseName}`,
38+
};
39+
}
3140
const content = await ide.readFile(problem.filepath);
3241
const lines = content.split("\n");
3342
const rangeContent = lines
@@ -40,7 +49,7 @@ class ProblemsContextProvider extends BaseContextProvider {
4049
return {
4150
description: "Problems in current file",
4251
content: `\`\`\`${relativePathOrBasename}\n${rangeContent}\n\`\`\`\n${problem.message}\n\n`,
43-
name: `Warning in ${baseName}`,
52+
name: `Warnings in ${baseName}`,
4453
};
4554
}),
4655
);

core/indexing/continueignore.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import fs from "fs";
2+
import { IDE } from "..";
3+
import { getGlobalContinueIgnorePath } from "../util/paths";
4+
import { gitIgArrayFromFile } from "./ignore";
5+
6+
export const getGlobalContinueIgArray = () => {
7+
const contents = fs.readFileSync(getGlobalContinueIgnorePath(), "utf8");
8+
return gitIgArrayFromFile(contents);
9+
};
10+
11+
export const getWorkspaceContinueIgArray = async (ide: IDE) => {
12+
const dirs = await ide.getWorkspaceDirs();
13+
return await dirs.reduce(
14+
async (accPromise, dir) => {
15+
const acc = await accPromise;
16+
try {
17+
const contents = await ide.readFile(`${dir}/.continueignore`);
18+
return [...acc, ...gitIgArrayFromFile(contents)];
19+
} catch (err) {
20+
console.error(err);
21+
return acc;
22+
}
23+
},
24+
Promise.resolve([] as string[]),
25+
);
26+
};

0 commit comments

Comments
 (0)