-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat(regex): initial commit * feat(regex): generateRegexSuggestions function * feat(regex): fix * feat(regex): regex search working * feat: add tests for regexp check * fix: typo in one of the regex rules * chore: merge regexp code with main branch * chore: merge regexp code with main branch * fix: correct call to createRegexComments * fix: remove stale tests --------- Co-authored-by: Alfonso Graziano <[email protected]>
- Loading branch information
1 parent
487252b
commit 3d9934c
Showing
9 changed files
with
240 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { filterAcceptedFiles, filterOnlyModified } from '../utils.js' | ||
import regexRules from './rules.js' | ||
import { mapLineToDiff } from 'map-line-to-diff' | ||
|
||
/** | ||
* Finds and returns issues from a given diff string based on a set of regex rules. | ||
* | ||
* @param {string} diff - The diff string to analyze. | ||
* @param {Array<Object>} rules - An array of rules where each rule object should contain: | ||
* - `id` {string} The unique identifier for the rule. | ||
* - `regex` {RegExp} The regular expression to test against the diff content. | ||
* - `prompt` {string} The description or prompt for the rule. | ||
* @returns {Array<Object>} An array of issues found. Each issue object contains: | ||
* - `lineNumber` {number} The line number in the diff where the issue was found. | ||
* - `id` {string} The id of the rule that matched. | ||
* - `description` {string} The description or prompt of the rule that matched. | ||
*/ | ||
export const findRegexRulesInLine = (lineContent, rules) => { | ||
const issues = [] | ||
|
||
for (let rule of rules) { | ||
if (rule.regex.test(lineContent)) { | ||
issues.push(rule) | ||
} | ||
} | ||
|
||
return issues | ||
} | ||
|
||
export const createRegexSuggestions = gitDiff => { | ||
const acceptedFiles = filterAcceptedFiles(gitDiff) | ||
const filesWithModifiedLines = filterOnlyModified(acceptedFiles) | ||
const filesWithAddDiff = filesWithModifiedLines.filter(file => file.added) | ||
|
||
const comments = [] | ||
|
||
filesWithAddDiff.forEach(file => { | ||
file.modifiedLines.forEach(line => { | ||
if (!line.added) return | ||
const lineSuggestions = findRegexRulesInLine(line.line, regexRules).map( | ||
rule => rule.description | ||
) | ||
if (lineSuggestions.length === 0) return | ||
|
||
comments.push({ | ||
path: file.afterName, | ||
lineNumber: line.lineNumber, | ||
body: lineSuggestions | ||
}) | ||
}) | ||
}) | ||
|
||
return comments | ||
} | ||
|
||
function transformSuggestionsIntoComments(suggestions, rawDiff) { | ||
const comments = suggestions.map(s => { | ||
return { | ||
path: s.path, | ||
position: mapLineToDiff(rawDiff, s.filename, s.lineNumber), | ||
body: s.body | ||
} | ||
}) | ||
return comments | ||
} | ||
|
||
export const createRegexComments = (gitDiff, rawDiff) => { | ||
const suggestions = createRegexSuggestions(gitDiff) | ||
return transformSuggestionsIntoComments(suggestions, rawDiff) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
export default [ | ||
{ | ||
id: 'JSON_PARSE_USAGE', | ||
regex: /\bJSON\.parse\b/, | ||
description: | ||
'JSON.parse should be avoided in favor of a more secure alternative like fastify/secure-json-parse.' | ||
}, | ||
{ | ||
id: 'MD5_USAGE', | ||
regex: /\bMD5\b/i, | ||
description: 'Do not use MD5, use a better hashing algorithm like SHA256.' | ||
}, | ||
{ | ||
id: 'LOCALSTORAGE_USAGE', | ||
regex: /\blocalStorage\b/, | ||
description: | ||
"Avoid using localStorage for sensitive data as it's vulnerable to XSS attacks. Consider using HttpOnly cookies or other server-side storage solutions." | ||
}, | ||
{ | ||
id: 'EVAL_USAGE', | ||
regex: /eval\(/, | ||
description: | ||
'Avoid the use of `eval()`, as it poses security risks and can execute arbitrary code. Consider safer alternatives, or parse data without execution.' | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
tests/create-regex-suggestions/createRegexSuggestions.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { describe, test } from 'node:test' | ||
import assert from 'assert' | ||
import { createRegexSuggestions } from '../../functions/createReview/regex/index.js' | ||
|
||
describe('createRegexSuggestions tests', () => { | ||
test('Avoid JSON.parse()', () => { | ||
const gitDiff = [ | ||
{ | ||
added: true, | ||
deleted: false, | ||
beforeName: 'functions/createReview/astParsing/rules/J3.example.js', | ||
afterName: 'functions/createReview/astParsing/rules/J3.example.js', | ||
modifiedLines: [ | ||
{ | ||
added: true, | ||
lineNumber: 2, | ||
line: 'export function example() {' | ||
}, | ||
{ | ||
added: true, | ||
lineNumber: 3, | ||
line: " const obj = {'foo': 'bar'}" | ||
}, | ||
{ | ||
added: true, | ||
lineNumber: 4, | ||
line: '' | ||
}, | ||
{ | ||
added: true, | ||
lineNumber: 5, | ||
line: ' // expect: J3' | ||
}, | ||
{ | ||
added: true, | ||
lineNumber: 6, | ||
line: ' JSON.parse(JSON.stringify(obj))' | ||
}, | ||
{ | ||
added: true, | ||
lineNumber: 7, | ||
line: '}' | ||
} | ||
] | ||
} | ||
] | ||
|
||
const output = createRegexSuggestions(gitDiff) | ||
|
||
assert.deepEqual(output, [ | ||
{ | ||
path: 'functions/createReview/astParsing/rules/J3.example.js', | ||
lineNumber: 6, | ||
body: [ | ||
'JSON.parse should be avoided in favor of a more secure alternative like fastify/secure-json-parse.' | ||
] | ||
} | ||
]) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { describe, test } from 'node:test' | ||
import assert from 'node:assert' | ||
import { findRegexRulesInLine } from '../../functions/createReview/regex/index.js' | ||
import regexRules from '../../functions/createReview/regex/rules.js' | ||
|
||
describe('findRegexRulesInLine', () => { | ||
test('MD5_USAGE', () => { | ||
const rules = findRegexRulesInLine(' MD5(myString) ;', regexRules) | ||
assert.deepEqual( | ||
rules.map(r => { | ||
return { id: r.id } | ||
}), | ||
[ | ||
{ | ||
id: 'MD5_USAGE' | ||
} | ||
] | ||
) | ||
}) | ||
|
||
test('LOCALSTORAGE_USAGE', () => { | ||
const rules = findRegexRulesInLine( | ||
' localStorage.setItem("foo", "bar")', | ||
regexRules | ||
) | ||
|
||
assert.deepEqual( | ||
rules.map(r => { | ||
return { id: r.id } | ||
}), | ||
[ | ||
{ | ||
id: 'LOCALSTORAGE_USAGE' | ||
} | ||
] | ||
) | ||
}) | ||
|
||
test('EVAL_USAGE', () => { | ||
const rules = findRegexRulesInLine(' eval("const f = 2")', regexRules) | ||
|
||
assert.deepEqual( | ||
rules.map(r => { | ||
return { id: r.id } | ||
}), | ||
[ | ||
{ | ||
id: 'EVAL_USAGE' | ||
} | ||
] | ||
) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters