Skip to content

Commit f8b6f92

Browse files
authored
Enable Python (#10)
* Enable Python Support using the standard library AST parser
1 parent 1b4f5c1 commit f8b6f92

19 files changed

+1506
-283
lines changed

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@ This extension provides automatic reporting of security concerns from [Socket Se
44

55
## Ahead of Package Installation
66

7-
* `import` and `require` in Javascript are detected and given summary scores to show concerns with configurable overlays. These overlays will persist even after package installation.
7+
* Package imports in JavaScript and Python are detected and given summary scores to show concerns with configurable overlays. These overlays will persist even after package installation.
8+
9+
* Socket detects multiple alternate forms of package imports, including dynamic `import()` or `require` in JavaScript or `importlib.import_module` in Python.
810

911
## After Package Installation
1012

11-
Workspaces are against Socket's reporting utilities upon detection of `package.json` files. Note these also run prior to actual installation as the presence in `package.json` is enough.
13+
Workspaces are run against Socket's reporting utilities upon detection of JavaScript or Python dependencies. Note these also run prior to actual installation: presence in `package.json`, `requirements.txt`, or any other supported file is enough.
1214

13-
* `package.json` files and packages listed within are detected and run against more thorough issue reporting to see exact issues. These are listed in the "Problems" tab for easy access.
15+
* Package dependency files like `package.json` and `pyproject.toml` are run against more thorough issue reporting to see exact issues for each dependency. These are listed in the "Problems" tab for easy access.
1416

15-
* `import` and `require` of packages with issues found in reporting are provided hovers which also summarize their issues.
17+
* You can hover over package imports in JavaScript or Python code to see a summary of their issues.
1618

1719
## Pull Requests
1820

19-
* Simplified github application installation is provided as a code lense inside of `package.json` files by detecting the user/organization and setting up the installation workflow automatically with a simple click. These reports are more fully featured and include things such as transitive issue aggregation and diffing from one commit to another. If you want these features please install [the github app](https://github.com/marketplace/socket-security).
21+
* Simplified GitHub application installation is available as a code lens. It detects your username/organization and sets up the installation workflow automatically with a simple click. These reports are more extensive than the ones provided within the extension and include things such as transitive issue aggregation and diffing from one commit to another. If you want these features, please install [the GitHub app](https://github.com/marketplace/socket-security).
2022

2123
# Team Guide
2224

package-lock.json

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

package.json

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"Code Analysis",
1414
"Code Quality",
1515
"JavaScript",
16+
"Python",
1617
"Security",
1718
"Static Code Analysis",
1819
"TypeScript"
@@ -21,6 +22,7 @@
2122
"Code Analysis",
2223
"Code Quality",
2324
"JavaScript",
25+
"Python",
2426
"Security",
2527
"Static Code Analysis",
2628
"TypeScript"
@@ -31,8 +33,12 @@
3133
},
3234
"icon": "socket-square.png",
3335
"activationEvents": [
34-
"workspaceContains:**/package.json",
35-
"workspaceContains:**/socket.yml",
36+
"workspaceContains:**/[pP][aA][cC][kK][aA][gG][eE].[jJ][sS][oO][nN]",
37+
"workspaceContains:**/[sS][oO][cC][kK][eE][tT].[yY][mM][lL]",
38+
"workspaceContains:**/{*[rR][eE][qQ][uU][iI][rR][eE][mM][eE][nN][tT][sS].[tT][xX][tT],[rR][eE][qQ][uU][iI][rR][eE][mM][eE][nN][tT][sS]/*.[tT][xX][tT],[rR][eE][qQ][uU][iI][rR][eE][mM][eE][nN][tT][sS]-*.[tT][xX][tT],[rR][eE][qQ][uU][iI][rR][eE][mM][eE][nN][tT][sS].[fF][rR][oO][zZ][eE][nN]}",
39+
"workspaceContains:**/[pP][yY][pP][rR][oO][jJ][eE][cC][tT].[tT][oO][mM][lL]",
40+
"workspaceContains:**/[pP][iI][pP][fF][iI][lL][eE]",
41+
"onLanguage:python",
3642
"onLanguage:javascript"
3743
],
3844
"type": "commonjs",
@@ -95,6 +101,14 @@
95101
"type": "boolean",
96102
"default": true,
97103
"description": "Create reports from package manifest files (package.json / package-lock.json) that require sending data remotely. Disabling this will disable all issues but keep scores listed."
104+
},
105+
"socket-security.pythonInterpreter": {
106+
"order": 5,
107+
"type": "string",
108+
"description": "Path to a Python interpreter to use for Socket dependency analysis.",
109+
"examples": [
110+
"/usr/bin/python"
111+
]
98112
}
99113
}
100114
}
@@ -117,11 +131,13 @@
117131
"@babel/parser": "^7.20.7",
118132
"@socketsecurity/config": "^2.0.0",
119133
"acorn-walk": "^8.2.0",
134+
"antlr4": "^4.13.0",
120135
"ast-types": "^0.14.2",
121136
"form-data-encoder": "^3.0.0",
122137
"formdata-node": "^5.0.1",
123138
"ini": "^3.0.1",
124139
"json-to-ast": "^2.1.0",
140+
"micromatch": "^4.0.5",
125141
"octokit": "^2.0.10",
126142
"safe-stable-stringify": "^2.4.1",
127143
"semver": "^7.3.8",
@@ -136,6 +152,7 @@
136152
"@typescript-eslint/parser": "^5.42.0",
137153
"esbuild": "^0.16.7",
138154
"eslint": "^8.26.0",
155+
"toml-eslint-parser": "^0.6.0",
139156
"typescript": "^4.8.4",
140157
"vsce": "^2.15.0"
141158
},

src/data/github.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as vscode from 'vscode'
2-
import {workspace} from 'vscode'
2+
import { parseTOML, getStaticTOMLValue } from 'toml-eslint-parser';
33
import ini from 'ini'
44
import { Octokit } from 'octokit';
55
import { getWorkspaceFolderURI } from '../util';
@@ -22,7 +22,7 @@ async function sniffForGithubOrgOrUser(workspaceRootURI: vscode.Uri): Promise<st
2222
// package.json repository
2323
try {
2424
const pkg = JSON.parse(
25-
Buffer.from(await workspace.fs.readFile(
25+
Buffer.from(await vscode.workspace.fs.readFile(
2626
vscode.Uri.joinPath(workspaceRootURI, 'package.json')
2727
)).toString()
2828
)
@@ -37,12 +37,32 @@ async function sniffForGithubOrgOrUser(workspaceRootURI: vscode.Uri): Promise<st
3737
const found = orgOrUserFromString(url)
3838
if (found) return found
3939
}
40-
} catch (e) {
41-
}
40+
} catch (e) {}
41+
42+
// poetry in pyproject.toml
43+
try {
44+
const pyproject = getStaticTOMLValue(parseTOML(
45+
Buffer.from(await vscode.workspace.fs.readFile(
46+
vscode.Uri.joinPath(workspaceRootURI, 'pyproject.toml')
47+
)).toString()
48+
)) as {
49+
tool?: {
50+
poetry?: {
51+
repository?: string;
52+
}
53+
}
54+
};
55+
const url = pyproject.tool?.poetry?.repository;
56+
if (url) {
57+
const found = orgOrUserFromString(url)
58+
if (found) return found
59+
}
60+
} catch (e) {}
61+
4262
// git remotes?
4363
try {
4464
const gitConfig = ini.parse(
45-
Buffer.from(await workspace.fs.readFile(
65+
Buffer.from(await vscode.workspace.fs.readFile(
4666
vscode.Uri.joinPath(workspaceRootURI, '.git', 'config')
4767
)).toString()
4868
)
@@ -55,7 +75,7 @@ async function sniffForGithubOrgOrUser(workspaceRootURI: vscode.Uri): Promise<st
5575
}
5676
}
5777
}
58-
} catch {}
78+
} catch (e) {}
5979
}
6080

6181
export function installGithubApp(uri: vscode.Uri) {

src/data/glob-patterns.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { IncomingMessage } from 'node:http';
2+
import * as https from 'node:https';
3+
import { once } from 'node:stream';
4+
import { text } from 'stream/consumers';
5+
6+
export type GlobPatterns = Record<string, Record<string, { pattern: string }>>
7+
8+
let globPatternsPromise: Promise<GlobPatterns> | undefined;
9+
10+
const replaceCasedChars = (chars: string) =>
11+
chars.replace(/[a-zA-Z]/g, c => `[${c.toLowerCase()}${c.toUpperCase()}]`)
12+
13+
// TODO: can VSCode do case insensitive match without this?
14+
function caseDesensitize(pattern: string) {
15+
let out = '';
16+
const charGroup = /\[[^\]]+?\]/g
17+
let lastIndex = 0;
18+
for (let match: RegExpExecArray | null = null; match = charGroup.exec(pattern);) {
19+
out += replaceCasedChars(pattern.slice(lastIndex, match.index)) + match[0];
20+
lastIndex = match.index + match[0].length;
21+
}
22+
out += replaceCasedChars(pattern.slice(lastIndex));
23+
return out;
24+
}
25+
26+
export async function getGlobPatterns() {
27+
if (!globPatternsPromise) {
28+
const req = https.get('https://api.socket.dev/v0/report/supported')
29+
req.end()
30+
globPatternsPromise = (once(req, 'response') as Promise<[IncomingMessage]>)
31+
.then(async ([res]) => {
32+
const result = JSON.parse(await text(res))
33+
if (res.statusCode !== 200) {
34+
throw new Error(result.error.message)
35+
}
36+
for (const eco in result) {
37+
for (const name in result[eco]) {
38+
const target = result[eco][name];
39+
target.pattern = caseDesensitize(target.pattern)
40+
}
41+
}
42+
return result
43+
}).
44+
catch(err => {
45+
// allow retry
46+
globPatternsPromise = undefined
47+
throw err
48+
})
49+
}
50+
return globPatternsPromise
51+
}

0 commit comments

Comments
 (0)