sudeshi-code-review 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -7
- package/dist/analyzer/createSourceFile.d.ts +9 -0
- package/dist/analyzer/createSourceFile.d.ts.map +1 -0
- package/dist/analyzer/createSourceFile.js +17 -0
- package/dist/analyzer/createSourceFile.js.map +1 -0
- package/dist/analyzer/rules/dangerousHtml.d.ts.map +1 -1
- package/dist/analyzer/rules/dangerousHtml.js +2 -1
- package/dist/analyzer/rules/dangerousHtml.js.map +1 -1
- package/dist/analyzer/rules/hardcodedSecret.d.ts.map +1 -1
- package/dist/analyzer/rules/hardcodedSecret.js +86 -52
- package/dist/analyzer/rules/hardcodedSecret.js.map +1 -1
- package/dist/analyzer/rules/unsafeLink.d.ts.map +1 -1
- package/dist/analyzer/rules/unsafeLink.js +60 -18
- package/dist/analyzer/rules/unsafeLink.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +14 -7
- package/dist/cli.js.map +1 -1
- package/dist/review/reviewEngine.d.ts +2 -0
- package/dist/review/reviewEngine.d.ts.map +1 -1
- package/dist/review/reviewEngine.js +214 -8
- package/dist/review/reviewEngine.js.map +1 -1
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Sudeshi Code Review
|
|
2
2
|
|
|
3
|
-
A TypeScript and React code-review CLI that scans JavaScript and TypeScript repositories for selected security patterns and produces
|
|
3
|
+
A TypeScript and React code-review CLI that scans JavaScript and TypeScript repositories for selected security patterns and produces Markdown or JSON reports. Optional AI-assisted analysis is powered by Sarvam AI.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- Scans JavaScript and TypeScript repositories.
|
|
7
|
+
- Scans JavaScript and TypeScript repositories, including JSX and TSX source files.
|
|
8
8
|
- Detects selected dangerous HTML insertion patterns, hardcoded secrets, and JavaScript URLs in JSX links.
|
|
9
|
-
- Reports findings with severity and evidence in Markdown.
|
|
9
|
+
- Reports findings with severity and evidence in Markdown or JSON, with support for saving reports to a file.
|
|
10
10
|
- Works without an AI API key using deterministic rules.
|
|
11
11
|
- Supports optional Sarvam AI analysis using your own API key.
|
|
12
12
|
- Includes automated tests for scanning, rules, reporting, and AI-provider behavior.
|
|
@@ -50,11 +50,35 @@ Show the installed version:
|
|
|
50
50
|
sudeshi-code-review --version
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
### Choose a report format and destination
|
|
54
|
+
|
|
55
|
+
Interactive terminals display a formatted terminal summary by default. When output is redirected or the process is non-interactive, the default report is Markdown.
|
|
56
|
+
|
|
57
|
+
Generate machine-readable JSON:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
sudeshi-code-review /path/to/repository --format json
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Save a Markdown report:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
sudeshi-code-review /path/to/repository --output report.md
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Save a JSON report:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
sudeshi-code-review /path/to/repository --format json --output report.json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The repository path comes first; place options after it. Use `--help` for the complete list of options and examples.
|
|
76
|
+
|
|
77
|
+
Review findings and validate them before acting on them.
|
|
54
78
|
|
|
55
79
|
### Terminal output
|
|
56
80
|
|
|
57
|
-
Interactive terminals display a formatted summary with severity-colored findings and confidence details. Color output is automatically disabled when stdout is not an interactive terminal or when the `NO_COLOR` environment variable is set. JSON
|
|
81
|
+
Interactive terminals display a formatted summary with severity-colored findings and confidence details. Color output is automatically disabled when stdout is not an interactive terminal or when the `NO_COLOR` environment variable is set. JSON selected with `--format json` remains machine-readable and contains no terminal styling.
|
|
58
82
|
|
|
59
83
|
Disable terminal colors explicitly:
|
|
60
84
|
|
|
@@ -102,7 +126,15 @@ When AI review is enabled, selected source context is sent to Sarvam AI for anal
|
|
|
102
126
|
| `hardcoded-secret` | Detects selected hardcoded credential patterns. |
|
|
103
127
|
| `unsafe-link` | Detects JavaScript URLs in JSX link targets. |
|
|
104
128
|
|
|
105
|
-
These rules cover selected patterns, not every possible instance of these issues.
|
|
129
|
+
These rules cover selected patterns, not every possible instance of these issues. Repository scanning supports `.js`, `.jsx`, `.ts`, and `.tsx` source files.
|
|
130
|
+
|
|
131
|
+
### Detection scope and interpretation
|
|
132
|
+
|
|
133
|
+
- **`dangerous-html`:** Flags selected uses of `dangerouslySetInnerHTML`. The rule detects the HTML-insertion sink; it does not establish that the supplied value is attacker-controlled or prove that an exploitable XSS vulnerability exists. A narrowly scoped static JSON-LD case is exempted by the rule.
|
|
134
|
+
- **`hardcoded-secret`:** Detects non-empty static strings and static template literals assigned to supported secret-like variable names or object-property keys, including quoted and statically computed property keys. Database URL values are flagged when they contain embedded username and password credentials. Detected secret literals are redacted from finding evidence, but arbitrary secret formats and dynamically constructed values are outside the rule's coverage.
|
|
135
|
+
- **`unsafe-link`:** Detects statically identifiable `javascript:` URLs in JSX `href` attributes, including direct string expressions, static template expressions, and supported locally resolvable variable values. It does not perform comprehensive data-flow analysis of dynamic values.
|
|
136
|
+
|
|
137
|
+
Finding severity describes the potential impact of a matched pattern. Rule confidence describes confidence in the pattern match; neither value proves exploitability or attacker control. Review the source context before treating a finding as a confirmed vulnerability.
|
|
106
138
|
|
|
107
139
|
## Limitations and responsible use
|
|
108
140
|
|
|
@@ -113,7 +145,7 @@ Sudeshi Code Review is a focused static-analysis tool—not a complete security
|
|
|
113
145
|
- Detection is limited to the currently implemented JavaScript and TypeScript rules.
|
|
114
146
|
- A clean report does not establish that a repository is secure.
|
|
115
147
|
- AI assessments can be inaccurate and require human review.
|
|
116
|
-
-
|
|
148
|
+
- AI-context redaction is best-effort. It attempts to redact recognized secret values in supported code patterns and selected repeated occurrences, but cannot guarantee that every secret will be detected or removed. Dynamically constructed values and syntax the implementation does not recognize may still be sent to the configured AI provider.
|
|
117
149
|
- Review the privacy implications before enabling AI review on private or sensitive repositories.
|
|
118
150
|
|
|
119
151
|
## Development
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Create an AST using the language variant appropriate for the input file.
|
|
4
|
+
*
|
|
5
|
+
* JavaScript files use JSX parsing so React code that keeps JSX in `.js` files
|
|
6
|
+
* is analyzed as well. TypeScript's JSX variant is reserved for `.tsx`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createSourceFile(filePath: string, content: string): ts.SourceFile;
|
|
9
|
+
//# sourceMappingURL=createSourceFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSourceFile.d.ts","sourceRoot":"","sources":["../../src/analyzer/createSourceFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,EAAE,CAAC,UAAU,CAiBf"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Create an AST using the language variant appropriate for the input file.
|
|
4
|
+
*
|
|
5
|
+
* JavaScript files use JSX parsing so React code that keeps JSX in `.js` files
|
|
6
|
+
* is analyzed as well. TypeScript's JSX variant is reserved for `.tsx`.
|
|
7
|
+
*/
|
|
8
|
+
export function createSourceFile(filePath, content) {
|
|
9
|
+
const extension = filePath.slice(filePath.lastIndexOf('.')).toLowerCase();
|
|
10
|
+
const scriptKind = extension === '.tsx'
|
|
11
|
+
? ts.ScriptKind.TSX
|
|
12
|
+
: extension === '.jsx' || extension === '.js'
|
|
13
|
+
? ts.ScriptKind.JSX
|
|
14
|
+
: ts.ScriptKind.TS;
|
|
15
|
+
return ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, scriptKind);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=createSourceFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSourceFile.js","sourceRoot":"","sources":["../../src/analyzer/createSourceFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,QAAgB,EAChB,OAAe;IAEf,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAE1E,MAAM,UAAU,GACd,SAAS,KAAK,MAAM;QAClB,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG;QACnB,CAAC,CAAC,SAAS,KAAK,MAAM,IAAI,SAAS,KAAK,KAAK;YAC3C,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG;YACnB,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;IAEzB,OAAO,EAAE,CAAC,gBAAgB,CACxB,QAAQ,EACR,OAAO,EACP,EAAE,CAAC,YAAY,CAAC,MAAM,EACtB,IAAI,EACJ,UAAU,CACX,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dangerousHtml.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/dangerousHtml.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"dangerousHtml.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/dangerousHtml.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,eAAO,MAAM,iBAAiB,EAAE,IA+L/B,CAAC"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
+
import { createSourceFile } from '../createSourceFile.js';
|
|
2
3
|
export const dangerousHtmlRule = (file) => {
|
|
3
4
|
const lines = file.content.split('\n');
|
|
4
5
|
const findings = [];
|
|
5
|
-
const sourceFile =
|
|
6
|
+
const sourceFile = createSourceFile(file.path, file.content);
|
|
6
7
|
function findDeclarationInScope(node, name) {
|
|
7
8
|
let current = node.parent;
|
|
8
9
|
while (current) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dangerousHtml.js","sourceRoot":"","sources":["../../../src/analyzer/rules/dangerousHtml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"dangerousHtml.js","sourceRoot":"","sources":["../../../src/analyzer/rules/dangerousHtml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAI5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,CAAC,MAAM,iBAAiB,GAAS,CAAC,IAAgB,EAAE,EAAE;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAE7D,SAAS,sBAAsB,CAC7B,IAAa,EACb,IAAY;QAEZ,IAAI,OAAO,GAAwB,IAAI,CAAC,MAAM,CAAC;QAE/C,OAAO,OAAO,EAAE,CAAC;YACf,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpD,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;oBAC3C,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC;wBACvC,SAAS;oBACX,CAAC;oBAED,KAAK,MAAM,WAAW,IAAI,SAAS,CAAC,eAAe,CAAC,YAAY,EAAE,CAAC;wBACjE,IACE,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC;4BACjC,WAAW,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,EAC9B,CAAC;4BACD,OAAO,WAAW,CAAC;wBACrB,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IACE,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC;gBACjC,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC;gBAChC,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC;gBAC3B,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAC/B,CAAC;gBACD,mEAAmE;gBACnE,IAAI,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC7C,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;wBAChD,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC;4BACvC,SAAS;wBACX,CAAC;wBAED,KAAK,MAAM,WAAW,IAAI,SAAS,CAAC,eAAe,CAAC,YAAY,EAAE,CAAC;4BACjE,IACE,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC;gCACjC,WAAW,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,EAC9B,CAAC;gCACD,OAAO,WAAW,CAAC;4BACrB,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;QAC3B,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,SAAS,cAAc,CAAC,IAAqB;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QAEnC,IACE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC;YAChC,CAAC,EAAE,CAAC,uBAAuB,CAAC,OAAO,CAAC,EACpC,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IACE,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC;YACjC,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,EACjC,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CACtD,CAAC,SAAS,EAAgC,EAAE,CAC1C,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;YAC5B,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC;YAC/B,SAAS,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CACjC,CAAC;QAEF,IACE,CAAC,aAAa;YACd,CAAC,aAAa,CAAC,WAAW;YAC1B,CAAC,EAAE,CAAC,eAAe,CAAC,aAAa,CAAC,WAAW,CAAC;YAC9C,aAAa,CAAC,WAAW,CAAC,IAAI,KAAK,qBAAqB,EACxD,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QAErC,IACE,CAAC,WAAW;YACZ,CAAC,EAAE,CAAC,eAAe,CAAC,WAAW,CAAC;YAChC,CAAC,WAAW,CAAC,UAAU,EACvB,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC;QAE1C,IAAI,CAAC,EAAE,CAAC,yBAAyB,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,YAAY,GAAG,UAAU,CAAC,UAAU,CAAC,IAAI,CAC7C,CAAC,QAAQ,EAAqC,EAAE,CAC9C,EAAE,CAAC,oBAAoB,CAAC,QAAQ,CAAC;YACjC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC;gBAClE,CAAC,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAChC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CACxC,CAAC;QAEF,IAAI,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE,CAAC;YACpE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,CAAC;QAEtC,IACE,CAAC,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,UAAU,CAAC;YAC/C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW;YACzC,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAC5C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,KAAK,MAAM;YAC1C,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAC3B,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAEnC,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,WAAW,GAAG,sBAAsB,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEhE,OAAO,OAAO,CACZ,WAAW;YACX,WAAW,CAAC,WAAW;YACvB,EAAE,CAAC,yBAAyB,CAAC,WAAW,CAAC,WAAW,CAAC;YACrD,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CACtC,CAAC,QAAQ,EAAE,EAAE,CACX,EAAE,CAAC,oBAAoB,CAAC,QAAQ,CAAC;gBACjC,CAAC,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,WAAW,CAAC;oBACvC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC;oBAC/C,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,WAAW,CAAC;wBACzC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,WAAW;wBACvD,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,YAAY;wBACxD,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAC/D,CACF,CAAC;IACJ,CAAC;IAED,SAAS,KAAK,CAAC,IAAa;QAC1B,IACE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC;YACvB,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YAC1B,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,yBAAyB;YAC5C,CAAC,cAAc,CAAC,IAAI,CAAC,EACrB,CAAC;YACD,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,6BAA6B,CACvD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC1B,CAAC;YAEF,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,gBAAgB;gBACpB,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,MAAM;gBAChB,UAAU,EAAE,CAAC;gBACb,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,IAAI,GAAG,CAAC;gBACd,IAAI,EAAE,gBAAgB;gBACtB,OAAO,EACL,mLAAmL;gBACrL,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE;gBACnC,gBAAgB,EAAE,IAAI;aACvB,CAAC,CAAC;QACL,CAAC;QAED,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,CAAC;IAClB,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hardcodedSecret.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/hardcodedSecret.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hardcodedSecret.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/hardcodedSecret.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAyDvC,eAAO,MAAM,mBAAmB,EAAE,IA2GjC,CAAC"}
|
|
@@ -1,75 +1,109 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
+
import { createSourceFile } from '../createSourceFile.js';
|
|
2
3
|
const SECRET_NAME_PATTERN = /^(apiKey|api_key|paymentApiKey|accessToken|access_token|internalToken|internal_token|databaseUrl|database_url|password|secret|clientSecret|client_secret|token)$/i;
|
|
3
4
|
function isStaticSecretString(node) {
|
|
4
5
|
return ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node);
|
|
5
6
|
}
|
|
6
|
-
function
|
|
7
|
+
function getStaticPropertyName(name) {
|
|
8
|
+
if (ts.isIdentifier(name) ||
|
|
9
|
+
ts.isStringLiteral(name) ||
|
|
10
|
+
ts.isNoSubstitutionTemplateLiteral(name)) {
|
|
11
|
+
return name.text;
|
|
12
|
+
}
|
|
13
|
+
if (ts.isComputedPropertyName(name) &&
|
|
14
|
+
isStaticSecretString(name.expression)) {
|
|
15
|
+
return name.expression.text;
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
function isCredentialedDatabaseUrl(value) {
|
|
20
|
+
return /^[a-z][a-z0-9+.-]*:\/\/[^/@:]+:[^/@]+@/i.test(value);
|
|
21
|
+
}
|
|
22
|
+
function shouldReportSecret(name, value) {
|
|
7
23
|
if (!value) {
|
|
8
|
-
return
|
|
24
|
+
return false;
|
|
9
25
|
}
|
|
10
|
-
if (
|
|
11
|
-
|
|
26
|
+
if (/^(databaseUrl|database_url)$/i.test(name) &&
|
|
27
|
+
!isCredentialedDatabaseUrl(value)) {
|
|
28
|
+
return false;
|
|
12
29
|
}
|
|
13
|
-
return
|
|
30
|
+
return true;
|
|
14
31
|
}
|
|
15
32
|
export const hardcodedSecretRule = (file) => {
|
|
16
|
-
const
|
|
17
|
-
const
|
|
33
|
+
const sourceFile = createSourceFile(file.path, file.content);
|
|
34
|
+
const sourceLines = file.content.split(/\r?\n/);
|
|
35
|
+
const occurrences = [];
|
|
36
|
+
const staticLiterals = [];
|
|
37
|
+
function getLine(node) {
|
|
38
|
+
return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile))
|
|
39
|
+
.line;
|
|
40
|
+
}
|
|
41
|
+
function addOccurrence(literal) {
|
|
42
|
+
occurrences.push({ line: getLine(literal), literal });
|
|
43
|
+
}
|
|
18
44
|
function visit(node) {
|
|
45
|
+
if ((ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) &&
|
|
46
|
+
node.text) {
|
|
47
|
+
staticLiterals.push({ line: getLine(node), literal: node });
|
|
48
|
+
}
|
|
19
49
|
if (ts.isVariableDeclaration(node) &&
|
|
20
50
|
ts.isIdentifier(node.name) &&
|
|
21
51
|
SECRET_NAME_PATTERN.test(node.name.text) &&
|
|
22
52
|
node.initializer &&
|
|
23
|
-
isStaticSecretString(node.initializer)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (value) {
|
|
27
|
-
findings.push({
|
|
28
|
-
id: 'hardcoded-secret',
|
|
29
|
-
category: 'security',
|
|
30
|
-
severity: 'high',
|
|
31
|
-
confidence: 1,
|
|
32
|
-
file: file.path,
|
|
33
|
-
line: line + 1,
|
|
34
|
-
rule: 'hardcoded-secret',
|
|
35
|
-
message: 'A hardcoded secret may be present',
|
|
36
|
-
evidence: redactSecretEvidence(file.content.split('\n')[line]?.trim() ?? '', value, node.initializer.getText(sourceFile)),
|
|
37
|
-
requiresAIReview: true,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
53
|
+
isStaticSecretString(node.initializer) &&
|
|
54
|
+
shouldReportSecret(node.name.text, node.initializer.text)) {
|
|
55
|
+
addOccurrence(node.initializer);
|
|
40
56
|
}
|
|
41
|
-
if (ts.isPropertyAssignment(node)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
ts.forEachChild(node, visit);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
if (/^(databaseUrl|database_url)$/i.test(propertyName) &&
|
|
52
|
-
!/^[a-z][a-z0-9+.-]*:\/\/[^/@:]+:[^/@]+@/i.test(value)) {
|
|
53
|
-
ts.forEachChild(node, visit);
|
|
54
|
-
return;
|
|
57
|
+
if (ts.isPropertyAssignment(node)) {
|
|
58
|
+
const propertyName = getStaticPropertyName(node.name);
|
|
59
|
+
if (propertyName &&
|
|
60
|
+
SECRET_NAME_PATTERN.test(propertyName) &&
|
|
61
|
+
isStaticSecretString(node.initializer) &&
|
|
62
|
+
shouldReportSecret(propertyName, node.initializer.text)) {
|
|
63
|
+
addOccurrence(node.initializer);
|
|
55
64
|
}
|
|
56
|
-
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
|
|
57
|
-
findings.push({
|
|
58
|
-
id: 'hardcoded-secret',
|
|
59
|
-
category: 'security',
|
|
60
|
-
severity: 'high',
|
|
61
|
-
confidence: 1,
|
|
62
|
-
file: file.path,
|
|
63
|
-
line: line + 1,
|
|
64
|
-
rule: 'hardcoded-secret',
|
|
65
|
-
message: 'A hardcoded secret may be present',
|
|
66
|
-
evidence: redactSecretEvidence(file.content.split('\n')[line]?.trim() ?? '', value, node.initializer.getText(sourceFile)),
|
|
67
|
-
requiresAIReview: true,
|
|
68
|
-
});
|
|
69
65
|
}
|
|
70
66
|
ts.forEachChild(node, visit);
|
|
71
67
|
}
|
|
68
|
+
function redactEvidence(line) {
|
|
69
|
+
let evidence = sourceLines[line] ?? '';
|
|
70
|
+
const secretValues = new Set(occurrences
|
|
71
|
+
.filter((occurrence) => occurrence.line === line)
|
|
72
|
+
.map(({ literal }) => literal.text));
|
|
73
|
+
const literalsToRedact = staticLiterals
|
|
74
|
+
.filter((occurrence) => occurrence.line === line && secretValues.has(occurrence.literal.text))
|
|
75
|
+
.sort((left, right) => right.literal.getStart(sourceFile) -
|
|
76
|
+
left.literal.getStart(sourceFile));
|
|
77
|
+
const lineStart = sourceFile.getPositionOfLineAndCharacter(line, 0);
|
|
78
|
+
const lineEnd = lineStart + evidence.length;
|
|
79
|
+
for (const { literal } of literalsToRedact) {
|
|
80
|
+
const literalStart = literal.getStart(sourceFile);
|
|
81
|
+
const literalEnd = literal.getEnd();
|
|
82
|
+
const start = Math.max(literalStart, lineStart) - lineStart;
|
|
83
|
+
const end = Math.min(literalEnd, lineEnd) - lineStart;
|
|
84
|
+
if (start >= end) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const quote = literal.getText(sourceFile)[0] ?? "'";
|
|
88
|
+
evidence =
|
|
89
|
+
evidence.slice(0, start) +
|
|
90
|
+
`${quote}[REDACTED]${quote}` +
|
|
91
|
+
evidence.slice(end);
|
|
92
|
+
}
|
|
93
|
+
return evidence.trim();
|
|
94
|
+
}
|
|
72
95
|
visit(sourceFile);
|
|
73
|
-
return
|
|
96
|
+
return occurrences.map(({ line }) => ({
|
|
97
|
+
id: 'hardcoded-secret',
|
|
98
|
+
category: 'security',
|
|
99
|
+
severity: 'high',
|
|
100
|
+
confidence: 1,
|
|
101
|
+
file: file.path,
|
|
102
|
+
line: line + 1,
|
|
103
|
+
rule: 'hardcoded-secret',
|
|
104
|
+
message: 'A hardcoded secret may be present',
|
|
105
|
+
evidence: redactEvidence(line),
|
|
106
|
+
requiresAIReview: true,
|
|
107
|
+
}));
|
|
74
108
|
};
|
|
75
109
|
//# sourceMappingURL=hardcodedSecret.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hardcodedSecret.js","sourceRoot":"","sources":["../../../src/analyzer/rules/hardcodedSecret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"hardcodedSecret.js","sourceRoot":"","sources":["../../../src/analyzer/rules/hardcodedSecret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,mBAAmB,GACvB,mKAAmK,CAAC;AAStK,SAAS,oBAAoB,CAC3B,IAAmB;IAEnB,OAAO,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,+BAA+B,CAAC,IAAI,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAqB;IAClD,IACE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC;QACrB,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;QACxB,EAAE,CAAC,+BAA+B,CAAC,IAAI,CAAC,EACxC,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,IACE,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC;QAC/B,oBAAoB,CAAC,IAAI,CAAC,UAAU,CAAC,EACrC,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;IAC9B,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAa;IAC9C,OAAO,yCAAyC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY,EAAE,KAAa;IACrD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IACE,+BAA+B,CAAC,IAAI,CAAC,IAAI,CAAC;QAC1C,CAAC,yBAAyB,CAAC,KAAK,CAAC,EACjC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAS,CAAC,IAAI,EAAE,EAAE;IAChD,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,WAAW,GAAuB,EAAE,CAAC;IAC3C,MAAM,cAAc,GAAuB,EAAE,CAAC;IAE9C,SAAS,OAAO,CAAC,IAAa;QAC5B,OAAO,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;aACvE,IAAI,CAAC;IACV,CAAC;IAED,SAAS,aAAa,CAAC,OAA4B;QACjD,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,SAAS,KAAK,CAAC,IAAa;QAC1B,IACE,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,+BAA+B,CAAC,IAAI,CAAC,CAAC;YACtE,IAAI,CAAC,IAAI,EACT,CAAC;YACD,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,IACE,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC;YAC9B,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YAC1B,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACxC,IAAI,CAAC,WAAW;YAChB,oBAAoB,CAAC,IAAI,CAAC,WAAW,CAAC;YACtC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EACzD,CAAC;YACD,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAClC,CAAC;QAED,IAAI,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,MAAM,YAAY,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEtD,IACE,YAAY;gBACZ,mBAAmB,CAAC,IAAI,CAAC,YAAY,CAAC;gBACtC,oBAAoB,CAAC,IAAI,CAAC,WAAW,CAAC;gBACtC,kBAAkB,CAAC,YAAY,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EACvD,CAAC;gBACD,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QAED,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,SAAS,cAAc,CAAC,IAAY;QAClC,IAAI,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAEvC,MAAM,YAAY,GAAG,IAAI,GAAG,CAC1B,WAAW;aACR,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,KAAK,IAAI,CAAC;aAChD,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CACtC,CAAC;QAEF,MAAM,gBAAgB,GAAG,cAAc;aACpC,MAAM,CACL,CAAC,UAAU,EAAE,EAAE,CACb,UAAU,CAAC,IAAI,KAAK,IAAI,IAAI,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CACxE;aACA,IAAI,CACH,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACd,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;YAClC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CACpC,CAAC;QAEJ,MAAM,SAAS,GAAG,UAAU,CAAC,6BAA6B,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC;QAE5C,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,gBAAgB,EAAE,CAAC;YAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,SAAS,CAAC,GAAG,SAAS,CAAC;YAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;YAEtD,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;gBACjB,SAAS;YACX,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;YACpD,QAAQ;gBACN,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;oBACxB,GAAG,KAAK,aAAa,KAAK,EAAE;oBAC5B,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,CAAC;IAElB,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACpC,EAAE,EAAE,kBAAkB;QACtB,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,MAAM;QAChB,UAAU,EAAE,CAAC;QACb,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,GAAG,CAAC;QACd,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,mCAAmC;QAC5C,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC;QAC9B,gBAAgB,EAAE,IAAI;KACvB,CAAC,CAAC,CAAC;AACN,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unsafeLink.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/unsafeLink.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"unsafeLink.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/unsafeLink.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,eAAO,MAAM,cAAc,EAAE,IAyK5B,CAAC"}
|
|
@@ -1,28 +1,66 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
+
import { createSourceFile } from '../createSourceFile.js';
|
|
2
3
|
export const unsafeLinkRule = (file) => {
|
|
3
4
|
const findings = [];
|
|
4
|
-
const sourceFile =
|
|
5
|
+
const sourceFile = createSourceFile(file.path, file.content);
|
|
6
|
+
function unwrapParentheses(node) {
|
|
7
|
+
let expression = node;
|
|
8
|
+
while (ts.isParenthesizedExpression(expression)) {
|
|
9
|
+
expression = expression.expression;
|
|
10
|
+
}
|
|
11
|
+
return expression;
|
|
12
|
+
}
|
|
5
13
|
function isDangerousString(node) {
|
|
6
|
-
|
|
7
|
-
|
|
14
|
+
const expression = unwrapParentheses(node);
|
|
15
|
+
if (!ts.isStringLiteral(expression) &&
|
|
16
|
+
!ts.isNoSubstitutionTemplateLiteral(expression)) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
// The URL parser removes ASCII tabs and newlines before scheme parsing,
|
|
20
|
+
// but an ordinary space inside the scheme makes it a different URL.
|
|
21
|
+
const normalizedValue = expression.text.replace(/[\t\n\r]/g, '');
|
|
22
|
+
return /^\s*javascript:/i.test(normalizedValue);
|
|
23
|
+
}
|
|
24
|
+
function bindingContainsName(bindingName, name) {
|
|
25
|
+
if (ts.isIdentifier(bindingName)) {
|
|
26
|
+
return bindingName.text === name;
|
|
27
|
+
}
|
|
28
|
+
return bindingName.elements.some((element) => ts.isBindingElement(element) && bindingContainsName(element.name, name));
|
|
29
|
+
}
|
|
30
|
+
function isFunctionLike(node) {
|
|
31
|
+
return (ts.isFunctionDeclaration(node) ||
|
|
32
|
+
ts.isFunctionExpression(node) ||
|
|
33
|
+
ts.isArrowFunction(node) ||
|
|
34
|
+
ts.isMethodDeclaration(node) ||
|
|
35
|
+
ts.isConstructorDeclaration(node) ||
|
|
36
|
+
ts.isGetAccessorDeclaration(node) ||
|
|
37
|
+
ts.isSetAccessorDeclaration(node));
|
|
8
38
|
}
|
|
9
39
|
function findVisibleDeclaration(reference) {
|
|
10
40
|
let current = reference.parent;
|
|
11
41
|
while (current) {
|
|
12
42
|
if (ts.isBlock(current) || ts.isSourceFile(current)) {
|
|
13
|
-
|
|
14
|
-
if (!ts.isVariableStatement(statement))
|
|
15
|
-
|
|
16
|
-
for (const declaration of statement.declarationList.declarations) {
|
|
17
|
-
if (ts.isIdentifier(declaration.name) &&
|
|
18
|
-
declaration.name.text === reference.text &&
|
|
19
|
-
declaration.initializer &&
|
|
20
|
-
declaration.getStart(sourceFile) < reference.getStart(sourceFile)) {
|
|
21
|
-
return declaration;
|
|
22
|
-
}
|
|
43
|
+
const declarations = current.statements.flatMap((statement) => {
|
|
44
|
+
if (!ts.isVariableStatement(statement)) {
|
|
45
|
+
return [];
|
|
23
46
|
}
|
|
47
|
+
return statement.declarationList.declarations.filter((declaration) => ts.isIdentifier(declaration.name) &&
|
|
48
|
+
declaration.name.text === reference.text);
|
|
49
|
+
});
|
|
50
|
+
if (declarations.length > 0) {
|
|
51
|
+
const precedingDeclaration = declarations
|
|
52
|
+
.filter((declaration) => declaration.getStart(sourceFile) <
|
|
53
|
+
reference.getStart(sourceFile))
|
|
54
|
+
.at(-1);
|
|
55
|
+
// A later declaration still shadows outer bindings in this scope.
|
|
56
|
+
return precedingDeclaration;
|
|
24
57
|
}
|
|
25
58
|
}
|
|
59
|
+
if (isFunctionLike(current) &&
|
|
60
|
+
current.parameters.some((parameter) => bindingContainsName(parameter.name, reference.text))) {
|
|
61
|
+
// A parameter shadows same-named declarations in outer scopes.
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
26
64
|
current = current.parent;
|
|
27
65
|
}
|
|
28
66
|
return undefined;
|
|
@@ -34,11 +72,15 @@ export const unsafeLinkRule = (file) => {
|
|
|
34
72
|
node.initializer) {
|
|
35
73
|
let dangerous = false;
|
|
36
74
|
if (ts.isStringLiteral(node.initializer)) {
|
|
37
|
-
dangerous =
|
|
75
|
+
dangerous = isDangerousString(node.initializer);
|
|
38
76
|
}
|
|
39
|
-
else if (ts.isJsxExpression(node.initializer)
|
|
40
|
-
|
|
41
|
-
|
|
77
|
+
else if (ts.isJsxExpression(node.initializer) &&
|
|
78
|
+
node.initializer.expression) {
|
|
79
|
+
const expression = unwrapParentheses(node.initializer.expression);
|
|
80
|
+
if (isDangerousString(expression)) {
|
|
81
|
+
dangerous = true;
|
|
82
|
+
}
|
|
83
|
+
else if (ts.isIdentifier(expression)) {
|
|
42
84
|
const declaration = findVisibleDeclaration(expression);
|
|
43
85
|
dangerous = Boolean(declaration?.initializer &&
|
|
44
86
|
isDangerousString(declaration.initializer));
|
|
@@ -55,7 +97,7 @@ export const unsafeLinkRule = (file) => {
|
|
|
55
97
|
line: line + 1,
|
|
56
98
|
rule: 'unsafe-link',
|
|
57
99
|
message: 'JavaScript URLs in links can execute code when activated.',
|
|
58
|
-
evidence: file.content.split(
|
|
100
|
+
evidence: file.content.split(/\r?\n/)[line]?.trim() ?? '',
|
|
59
101
|
requiresAIReview: true,
|
|
60
102
|
});
|
|
61
103
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unsafeLink.js","sourceRoot":"","sources":["../../../src/analyzer/rules/unsafeLink.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"unsafeLink.js","sourceRoot":"","sources":["../../../src/analyzer/rules/unsafeLink.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,IAAI,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAK3D,OAAO,KAAK,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAQjF,KAAK,eAAe,GAAG;IACrB,cAAc,EAAE,OAAO,qBAAqB,CAAC;IAC7C,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,CAAC;IAC5C,YAAY,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;CACjD,CAAC;AAQF,wBAAsB,MAAM,CAC1B,IAAI,EAAE,MAAM,EAAE,EACd,YAAY,GAAE,eAQb,GACA,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,IAAI,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAK3D,OAAO,KAAK,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAQjF,KAAK,eAAe,GAAG;IACrB,cAAc,EAAE,OAAO,qBAAqB,CAAC;IAC7C,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,CAAC;IAC5C,YAAY,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;CACjD,CAAC;AAQF,wBAAsB,MAAM,CAC1B,IAAI,EAAE,MAAM,EAAE,EACd,YAAY,GAAE,eAQb,GACA,OAAO,CAAC,IAAI,CAAC,CAgJf"}
|
package/dist/cli.js
CHANGED
|
@@ -29,17 +29,24 @@ export async function runCLI(args, dependencies = {
|
|
|
29
29
|
'Sudeshi Code Review',
|
|
30
30
|
'',
|
|
31
31
|
'Usage:',
|
|
32
|
-
' sudeshi-code-review <repository-path>',
|
|
32
|
+
' sudeshi-code-review <repository-path> [options]',
|
|
33
|
+
' sudeshi-code-review --help',
|
|
34
|
+
' sudeshi-code-review --version',
|
|
33
35
|
'',
|
|
34
36
|
'Options:',
|
|
35
|
-
' -h, --help
|
|
36
|
-
' -v, --version
|
|
37
|
-
' --format <format>
|
|
38
|
-
' --output <path>
|
|
37
|
+
' -h, --help Show this help message',
|
|
38
|
+
' -v, --version Show the installed version',
|
|
39
|
+
' --format <format> Report format: markdown or json (default: markdown)',
|
|
40
|
+
' --output <path> Save the report to a file instead of stdout',
|
|
41
|
+
'',
|
|
42
|
+
'Examples:',
|
|
43
|
+
' sudeshi-code-review ./my-app',
|
|
44
|
+
' sudeshi-code-review ./my-app --format json',
|
|
45
|
+
' sudeshi-code-review ./my-app --format json --output report.json',
|
|
39
46
|
'',
|
|
40
47
|
'Environment:',
|
|
41
|
-
' SARVAM_API_KEY
|
|
42
|
-
' NO_COLOR
|
|
48
|
+
' SARVAM_API_KEY Optional API key for AI-assisted review',
|
|
49
|
+
' NO_COLOR Disable terminal colors when set',
|
|
43
50
|
'',
|
|
44
51
|
].join('\n'));
|
|
45
52
|
return;
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,IAAI,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAGtF,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGhE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAQzE,SAAS,aAAa,CAAC,OAAe;IACpC,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,IAAc,EACd,eAAgC;IAC9B,cAAc,EAAE,qBAAqB;IACrC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,cAAc,CAAC,KAAK,EAAE;QACpB,iBAAiB;QACjB,mBAAmB;QACnB,cAAc;KACf,CAAC;CACL;IAED,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB;YACE,qBAAqB;YACrB,EAAE;YACF,QAAQ;YACR,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,8 @@ export declare class ReviewEngine {
|
|
|
17
17
|
private readonly config;
|
|
18
18
|
constructor(config: ReviewEngineConfig);
|
|
19
19
|
private redactHardcodedSecret;
|
|
20
|
+
private redactShortSecretOccurrences;
|
|
21
|
+
private redactKnownSecretValues;
|
|
20
22
|
private redactSecretValue;
|
|
21
23
|
review(input: ReviewInput): Promise<ReviewResult>;
|
|
22
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewEngine.d.ts","sourceRoot":"","sources":["../../src/review/reviewEngine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAG5D,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,UAAU,CAAC;CACtB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB,CAAC;
|
|
1
|
+
{"version":3,"file":"reviewEngine.d.ts","sourceRoot":"","sources":["../../src/review/reviewEngine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAG5D,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,UAAU,CAAC;CACtB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB,CAAC;AAyEF,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,kBAAkB;IAEvD,OAAO,CAAC,qBAAqB;IA2I7B,OAAO,CAAC,4BAA4B;IAkHpC,OAAO,CAAC,uBAAuB;IA6B/B,OAAO,CAAC,iBAAiB;IAkBnB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CA+FxD"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { buildContext } from '../context/buildContext.js';
|
|
3
3
|
const SECRET_ASSIGNMENT_PATTERN = String.raw `\b([\w$]*(?:api[_-]?key|password|secret|client[_-]?secret|token|database[_-]?url))\s*(=|:)\s*(?:(['"])((?:\\.|[^\\])*?)\3|(\`)((?:\\.|(?!\$\{)[^\\])*?)\5)`;
|
|
4
|
+
const MINIMUM_GLOBAL_REDACTION_LENGTH = 4;
|
|
5
|
+
const REDACTION_SENTINEL = '\u0000SUDESHI_SECRET_REDACTION_SENTINEL_7F3A\u0000';
|
|
4
6
|
function createSecretAssignmentRegex(global = false) {
|
|
5
7
|
return new RegExp(SECRET_ASSIGNMENT_PATTERN, global ? 'gi' : 'i');
|
|
6
8
|
}
|
|
@@ -8,12 +10,51 @@ function extractSecretValue(evidence) {
|
|
|
8
10
|
const match = evidence?.match(createSecretAssignmentRegex());
|
|
9
11
|
return match?.[4] ?? match?.[6];
|
|
10
12
|
}
|
|
13
|
+
function escapeRegExp(value) {
|
|
14
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
15
|
+
}
|
|
16
|
+
function getStaticPropertyName(name) {
|
|
17
|
+
if (ts.isIdentifier(name) ||
|
|
18
|
+
ts.isStringLiteral(name) ||
|
|
19
|
+
ts.isNoSubstitutionTemplateLiteral(name)) {
|
|
20
|
+
return name.text;
|
|
21
|
+
}
|
|
22
|
+
if (ts.isComputedPropertyName(name)) {
|
|
23
|
+
const expression = name.expression;
|
|
24
|
+
if (ts.isStringLiteral(expression) ||
|
|
25
|
+
ts.isNoSubstitutionTemplateLiteral(expression)) {
|
|
26
|
+
return expression.text;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
function hasStandaloneSecret(value, secret) {
|
|
32
|
+
if (!/^[\w$]+$/.test(secret)) {
|
|
33
|
+
return value === secret;
|
|
34
|
+
}
|
|
35
|
+
const pattern = new RegExp(`(?<![\\w$])${escapeRegExp(secret)}(?![\\w$])`);
|
|
36
|
+
return pattern.test(value);
|
|
37
|
+
}
|
|
38
|
+
function redactStandaloneSecret(value, secret) {
|
|
39
|
+
if (!/^[\w$]+$/.test(secret)) {
|
|
40
|
+
return value === secret ? '[REDACTED]' : value;
|
|
41
|
+
}
|
|
42
|
+
if (secret.length === 1) {
|
|
43
|
+
// A single character is too ambiguous to replace throughout prose/comments.
|
|
44
|
+
return value === secret ? '[REDACTED]' : value;
|
|
45
|
+
}
|
|
46
|
+
const pattern = new RegExp(`(?<![\\w$])${escapeRegExp(secret)}(?![\\w$])`, 'g');
|
|
47
|
+
return value
|
|
48
|
+
.split(REDACTION_SENTINEL)
|
|
49
|
+
.map((segment) => segment.replace(pattern, REDACTION_SENTINEL))
|
|
50
|
+
.join(REDACTION_SENTINEL);
|
|
51
|
+
}
|
|
11
52
|
export class ReviewEngine {
|
|
12
53
|
config;
|
|
13
54
|
constructor(config) {
|
|
14
55
|
this.config = config;
|
|
15
56
|
}
|
|
16
|
-
redactHardcodedSecret(source, filePath = 'source.ts') {
|
|
57
|
+
redactHardcodedSecret(source, filePath = 'source.ts', collectedSecretValues) {
|
|
17
58
|
const scriptKind = filePath.endsWith('.tsx')
|
|
18
59
|
? ts.ScriptKind.TSX
|
|
19
60
|
: filePath.endsWith('.jsx')
|
|
@@ -24,6 +65,22 @@ export class ReviewEngine {
|
|
|
24
65
|
const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, scriptKind);
|
|
25
66
|
const secretNamePattern = /(?:api[_-]?key|password|secret|client[_-]?secret|token|database[_-]?url)/i;
|
|
26
67
|
const edits = [];
|
|
68
|
+
const secretValues = collectedSecretValues ?? new Set();
|
|
69
|
+
function collectSecretValueParts(valueNode) {
|
|
70
|
+
if (ts.isStringLiteral(valueNode) ||
|
|
71
|
+
ts.isNoSubstitutionTemplateLiteral(valueNode)) {
|
|
72
|
+
if (valueNode.text && valueNode.text !== '[REDACTED]') {
|
|
73
|
+
secretValues.add(valueNode.text);
|
|
74
|
+
}
|
|
75
|
+
// Keep both decoded and source spellings (e.g. escaped quotes).
|
|
76
|
+
const rawValue = valueNode.getText(sourceFile).slice(1, -1);
|
|
77
|
+
if (rawValue && rawValue !== '[REDACTED]') {
|
|
78
|
+
secretValues.add(rawValue);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// This also visits string literals nested inside template expressions.
|
|
82
|
+
ts.forEachChild(valueNode, collectSecretValueParts);
|
|
83
|
+
}
|
|
27
84
|
function visit(node) {
|
|
28
85
|
let name;
|
|
29
86
|
let initializer;
|
|
@@ -31,8 +88,8 @@ export class ReviewEngine {
|
|
|
31
88
|
name = node.name.text;
|
|
32
89
|
initializer = node.initializer;
|
|
33
90
|
}
|
|
34
|
-
else if (ts.isPropertyAssignment(node)
|
|
35
|
-
name = node.name
|
|
91
|
+
else if (ts.isPropertyAssignment(node)) {
|
|
92
|
+
name = getStaticPropertyName(node.name);
|
|
36
93
|
initializer = node.initializer;
|
|
37
94
|
}
|
|
38
95
|
if (name &&
|
|
@@ -41,29 +98,164 @@ export class ReviewEngine {
|
|
|
41
98
|
(ts.isStringLiteral(initializer) ||
|
|
42
99
|
ts.isNoSubstitutionTemplateLiteral(initializer) ||
|
|
43
100
|
ts.isTemplateExpression(initializer))) {
|
|
44
|
-
|
|
101
|
+
const edit = {
|
|
45
102
|
start: initializer.getStart(sourceFile),
|
|
46
103
|
end: initializer.getEnd(),
|
|
104
|
+
};
|
|
105
|
+
// The AST traversal is parent-first. If this initializer overlaps an
|
|
106
|
+
// edit already selected for an outer secret initializer, do not add a
|
|
107
|
+
// second edit: applying overlapping ranges with original offsets can
|
|
108
|
+
// leave part of the outer template in the AI-bound source. Still
|
|
109
|
+
// collect nested literals so repeated values can be redacted elsewhere.
|
|
110
|
+
const overlapsExistingEdit = edits.some((existing) => edit.start < existing.end && existing.start < edit.end);
|
|
111
|
+
if (!overlapsExistingEdit) {
|
|
112
|
+
edits.push(edit);
|
|
113
|
+
}
|
|
114
|
+
collectSecretValueParts(initializer);
|
|
115
|
+
}
|
|
116
|
+
ts.forEachChild(node, visit);
|
|
117
|
+
}
|
|
118
|
+
visit(sourceFile);
|
|
119
|
+
let redactedSource = source;
|
|
120
|
+
// Replace the complete initializer, regardless of its length or syntax.
|
|
121
|
+
for (const edit of edits.sort((a, b) => b.start - a.start)) {
|
|
122
|
+
redactedSource =
|
|
123
|
+
redactedSource.slice(0, edit.start) +
|
|
124
|
+
"'" +
|
|
125
|
+
REDACTION_SENTINEL +
|
|
126
|
+
"'" +
|
|
127
|
+
redactedSource.slice(edit.end);
|
|
128
|
+
}
|
|
129
|
+
// The detector's evidence may already be redacted. Preserve known literal
|
|
130
|
+
// values and remove longer repeated occurrences elsewhere in AI-bound text.
|
|
131
|
+
// Short values are handled separately with literal- and token-aware matching.
|
|
132
|
+
const valuesToRedact = [...secretValues]
|
|
133
|
+
.filter((value) => value.length >= MINIMUM_GLOBAL_REDACTION_LENGTH)
|
|
134
|
+
.sort((a, b) => b.length - a.length);
|
|
135
|
+
for (const value of valuesToRedact) {
|
|
136
|
+
redactedSource = redactedSource
|
|
137
|
+
.split(REDACTION_SENTINEL)
|
|
138
|
+
.map((segment) => segment.replaceAll(value, REDACTION_SENTINEL))
|
|
139
|
+
.join(REDACTION_SENTINEL);
|
|
140
|
+
}
|
|
141
|
+
// Short values need narrower handling: redact matching string literals and
|
|
142
|
+
// bounded comment tokens instead of replacing arbitrary substrings in code.
|
|
143
|
+
const shortValues = [...secretValues]
|
|
144
|
+
.filter((value) => value.length > 0 && value.length < MINIMUM_GLOBAL_REDACTION_LENGTH)
|
|
145
|
+
.sort((a, b) => b.length - a.length);
|
|
146
|
+
for (const value of shortValues) {
|
|
147
|
+
redactedSource = this.redactShortSecretOccurrences(redactedSource, value, filePath);
|
|
148
|
+
}
|
|
149
|
+
return redactedSource.replaceAll(REDACTION_SENTINEL, '[REDACTED]');
|
|
150
|
+
}
|
|
151
|
+
redactShortSecretOccurrences(source, secret, filePath) {
|
|
152
|
+
const scriptKind = filePath.endsWith('.tsx')
|
|
153
|
+
? ts.ScriptKind.TSX
|
|
154
|
+
: filePath.endsWith('.jsx')
|
|
155
|
+
? ts.ScriptKind.JSX
|
|
156
|
+
: filePath.endsWith('.js')
|
|
157
|
+
? ts.ScriptKind.JS
|
|
158
|
+
: ts.ScriptKind.TS;
|
|
159
|
+
const languageVariant = scriptKind === ts.ScriptKind.TSX || scriptKind === ts.ScriptKind.JSX
|
|
160
|
+
? ts.LanguageVariant.JSX
|
|
161
|
+
: ts.LanguageVariant.Standard;
|
|
162
|
+
const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, scriptKind);
|
|
163
|
+
const edits = [];
|
|
164
|
+
function visit(node) {
|
|
165
|
+
if ((ts.isTemplateHead(node) ||
|
|
166
|
+
ts.isTemplateMiddle(node) ||
|
|
167
|
+
ts.isTemplateTail(node)) &&
|
|
168
|
+
!node.text.includes(REDACTION_SENTINEL) &&
|
|
169
|
+
hasStandaloneSecret(node.text, secret)) {
|
|
170
|
+
// Replace only the static template chunk, preserving delimiters such
|
|
171
|
+
// as `${` and `}` so the resulting template remains syntactically valid.
|
|
172
|
+
const start = node.getStart(sourceFile) + 1;
|
|
173
|
+
const suffixLength = ts.isTemplateTail(node) ? 1 : 2;
|
|
174
|
+
const end = node.getEnd() - suffixLength;
|
|
175
|
+
edits.push({
|
|
176
|
+
start,
|
|
177
|
+
end,
|
|
178
|
+
replacement: REDACTION_SENTINEL,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
else if ((ts.isStringLiteral(node) ||
|
|
182
|
+
ts.isNoSubstitutionTemplateLiteral(node)) &&
|
|
183
|
+
!node.text.includes(REDACTION_SENTINEL) &&
|
|
184
|
+
hasStandaloneSecret(node.text, secret)) {
|
|
185
|
+
const raw = node.getText(sourceFile);
|
|
186
|
+
const quote = raw[0] ?? "'";
|
|
187
|
+
edits.push({
|
|
188
|
+
start: node.getStart(sourceFile),
|
|
189
|
+
end: node.getEnd(),
|
|
190
|
+
replacement: `${quote}${REDACTION_SENTINEL}${quote}`,
|
|
47
191
|
});
|
|
48
192
|
}
|
|
49
193
|
ts.forEachChild(node, visit);
|
|
50
194
|
}
|
|
51
195
|
visit(sourceFile);
|
|
196
|
+
// Comments are trivia rather than AST nodes, so scan them separately. For
|
|
197
|
+
// single-character values, skip comment-wide replacement to avoid erasing
|
|
198
|
+
// ordinary prose; exact matching string literals are still handled above.
|
|
199
|
+
if (secret.length >= 2 && /^[\w$]+$/.test(secret)) {
|
|
200
|
+
const scanner = ts.createScanner(ts.ScriptTarget.Latest, false, languageVariant, source);
|
|
201
|
+
while (true) {
|
|
202
|
+
const token = scanner.scan();
|
|
203
|
+
if (token === ts.SyntaxKind.EndOfFileToken) {
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
if (token !== ts.SyntaxKind.SingleLineCommentTrivia &&
|
|
207
|
+
token !== ts.SyntaxKind.MultiLineCommentTrivia) {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const comment = scanner.getTokenText();
|
|
211
|
+
const redactedComment = redactStandaloneSecret(comment, secret);
|
|
212
|
+
if (redactedComment !== comment) {
|
|
213
|
+
edits.push({
|
|
214
|
+
start: scanner.getTokenPos(),
|
|
215
|
+
end: scanner.getTextPos(),
|
|
216
|
+
replacement: redactedComment,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
52
221
|
let redactedSource = source;
|
|
53
222
|
for (const edit of edits.sort((a, b) => b.start - a.start)) {
|
|
54
223
|
redactedSource =
|
|
55
224
|
redactedSource.slice(0, edit.start) +
|
|
56
|
-
|
|
225
|
+
edit.replacement +
|
|
57
226
|
redactedSource.slice(edit.end);
|
|
58
227
|
}
|
|
59
228
|
return redactedSource;
|
|
60
229
|
}
|
|
230
|
+
redactKnownSecretValues(value, secretValues) {
|
|
231
|
+
let redactedValue = value;
|
|
232
|
+
const valuesToRedact = [...secretValues]
|
|
233
|
+
.filter((secret) => secret.length > 0)
|
|
234
|
+
.sort((a, b) => b.length - a.length);
|
|
235
|
+
for (const secret of valuesToRedact) {
|
|
236
|
+
if (secret.length >= MINIMUM_GLOBAL_REDACTION_LENGTH) {
|
|
237
|
+
redactedValue = redactedValue.replaceAll(secret, '[REDACTED]');
|
|
238
|
+
}
|
|
239
|
+
else if (secret.length >= 2 && /^[\w$]+$/.test(secret)) {
|
|
240
|
+
const pattern = new RegExp(`(?<![\\w$])${escapeRegExp(secret)}(?![\\w$])`, 'g');
|
|
241
|
+
redactedValue = redactedValue.replace(pattern, '[REDACTED]');
|
|
242
|
+
}
|
|
243
|
+
else if (redactedValue === secret) {
|
|
244
|
+
// For one-character or punctuation-only values, only redact an exact
|
|
245
|
+
// field match; broad replacement would have excessive false positives.
|
|
246
|
+
redactedValue = '[REDACTED]';
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return redactedValue;
|
|
250
|
+
}
|
|
61
251
|
redactSecretValue(source, finding) {
|
|
62
252
|
if (finding.rule !== 'hardcoded-secret') {
|
|
63
253
|
return source;
|
|
64
254
|
}
|
|
65
255
|
const secret = extractSecretValue(finding.evidence);
|
|
66
|
-
if (!secret
|
|
256
|
+
if (!secret ||
|
|
257
|
+
secret === '[REDACTED]' ||
|
|
258
|
+
secret.length < MINIMUM_GLOBAL_REDACTION_LENGTH) {
|
|
67
259
|
return source;
|
|
68
260
|
}
|
|
69
261
|
return source.replaceAll(secret, '[REDACTED]');
|
|
@@ -83,14 +275,28 @@ export class ReviewEngine {
|
|
|
83
275
|
!extractSecretValue(finding.evidence)) {
|
|
84
276
|
continue;
|
|
85
277
|
}
|
|
278
|
+
const secretValues = new Set();
|
|
279
|
+
const secretFromEvidence = extractSecretValue(finding.evidence);
|
|
280
|
+
if (secretFromEvidence && secretFromEvidence !== '[REDACTED]') {
|
|
281
|
+
secretValues.add(secretFromEvidence);
|
|
282
|
+
}
|
|
86
283
|
const safeSourceFile = {
|
|
87
284
|
...sourceFile,
|
|
88
|
-
content: this.redactSecretValue(this.redactHardcodedSecret(sourceFile.content, sourceFile.path), finding),
|
|
285
|
+
content: this.redactSecretValue(this.redactHardcodedSecret(sourceFile.content, sourceFile.path, secretValues), finding),
|
|
89
286
|
};
|
|
90
287
|
const safeFinding = {
|
|
91
288
|
...finding,
|
|
289
|
+
file: this.redactKnownSecretValues(finding.file, secretValues),
|
|
290
|
+
message: this.redactKnownSecretValues(finding.message, secretValues),
|
|
92
291
|
...(finding.evidence !== undefined && {
|
|
93
|
-
evidence: this.redactSecretValue(this.redactHardcodedSecret(finding.evidence, sourceFile.path), finding),
|
|
292
|
+
evidence: this.redactKnownSecretValues(this.redactSecretValue(this.redactHardcodedSecret(finding.evidence, sourceFile.path, secretValues), finding), secretValues),
|
|
293
|
+
}),
|
|
294
|
+
...(finding.aiReview && {
|
|
295
|
+
aiReview: {
|
|
296
|
+
...finding.aiReview,
|
|
297
|
+
reason: this.redactKnownSecretValues(finding.aiReview.reason, secretValues),
|
|
298
|
+
recommendation: this.redactKnownSecretValues(finding.aiReview.recommendation, secretValues),
|
|
299
|
+
},
|
|
94
300
|
}),
|
|
95
301
|
};
|
|
96
302
|
const context = buildContext(safeSourceFile, safeFinding);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewEngine.js","sourceRoot":"","sources":["../../src/review/reviewEngine.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reviewEngine.js","sourceRoot":"","sources":["../../src/review/reviewEngine.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sudeshi-code-review",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A TypeScript and React code review CLI with security rules and optional Sarvam AI analysis.",
|
|
5
5
|
"homepage": "https://github.com/sriram23/sudeshi-code-review#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"author": "Sriram B",
|
|
15
15
|
"type": "module",
|
|
16
|
-
"main": "./dist/index.js",
|
|
17
16
|
"scripts": {
|
|
18
17
|
"build": "tsc",
|
|
19
18
|
"test": "vitest run",
|