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
4 changes: 3 additions & 1 deletion SECURITY_DEBT.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
# Known Security Debt

## 🔴 Pending — Requires Developer Fix
## 🟢 Fixed

### 1. Regex Injection / ReDoS in Company Search
- **File:** `app/api/company/route.js:120`
- **Risk:** `companyName` is received unsanitized from a query parameter and concatenated into a `RegExp`. This allows for ReDoS (server hang) and exact match bypass.
- **Suggested Fix:** Escape special regex characters before building the `RegExp`, or use an exact Mongo filter instead of `$regex`.
- **Detected by:** `eslint-plugin-security` (`detect-non-literal-regexp`), does not block CI (severity: warning).
- **Fix Applied:** Changed the previous regex to a Mongo filter and this way prevent Regex Injection and ReDoS

### 2. List Elements Without `key` (5 instances)
- **Files:** `app/settings/manage-contracts/AddContract.tsx:144`, `EditContract.tsx:156`, `components/ContractTable.jsx:99`, `components/datatable.tsx:363`, `components/datatableSeller1.tsx:275`
- **Risk:** Not a security issue — it is a React bug that can cause incorrect rendering when reordering/updating lists.
- **Suggested Fix:** Add `key={unique-id}` to each iterated element.
- **Note:** Temporarily downgraded to a warning via `eslint-disable-next-line` to avoid blocking the pipeline — see comments in each file.
- **Fix Applied:** Added a unique id key to each of the iterated element

## 🟢 Reviewed — False Positive, No Action Required

Expand Down
7 changes: 4 additions & 3 deletions app/api/company/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,11 @@ export async function GET(req) {
if (companyName) {
try {
await connectMongoDB()
// SECURITY DEBT: ver SECURITY_DEBT.md #1 — companyName no saneado antes de construir el RegExp (ReDoS + regex injection)

const company = await Company.findOne({
companyName: { $regex: new RegExp("^" + companyName + "$", "i") },
}).select()
companyName: companyName },
{},
{ collation: {locale: 'en', strength: 2}}).select()

return NextResponse.json({ company })
} catch (error) {
Expand Down
2 changes: 1 addition & 1 deletion app/settings/manage-contracts/AddContract.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ export default function AddContract(props) {
offerCompany.map(
(singleCompany, index) =>
!activeCompany.includes(singleCompany.companyName) && (
// eslint-disable-next-line react/jsx-key -- deuda conocida, ver SECURITY_DEBT.md #2, pendiente de fix
<SelectItem
key={singleCompany._id}
className="capitalize"
value={singleCompany.companyName}
>
Expand Down
2 changes: 1 addition & 1 deletion app/settings/manage-contracts/EditContract.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ export default function EditContract(props) {
offerCompany.map(
(singleCompany, index) =>
!activeCompany.includes(singleCompany.companyName) && (
// eslint-disable-next-line react/jsx-key -- deuda conocida, ver SECURITY_DEBT.md #2, pendiente de fix
<SelectItem
key={singleCompany._id}
className="capitalize"
value={singleCompany.companyName}
defaultValue={NewCompany}
Expand Down
4 changes: 1 addition & 3 deletions components/ContractTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,9 @@ const ContractTable = () => {
</TableCell>
<TableCell className="flex py-2 overflow-x-auto gap-x-2">
{singleUser.contracts.map((contract, index) => (
// eslint-disable-next-line react/jsx-key -- deuda conocida, ver SECURITY_DEBT.md #2, pendiente de fix
<div className="flex px-2 border rounded-md ">
<div className="flex px-2 border rounded-md" key={index}>
<span
className="inline-block px-4 py-1 mr-2 capitalize bg-white rounded"
key={index}
>
{contract.companyName} | {contract.rate}%
</span>
Expand Down
3 changes: 1 addition & 2 deletions components/datatable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,7 @@ export default function DataTable(props) {
<ScrollArea className="h-40">
<SelectItem value="">All</SelectItem>
{Allcompanies.map((company) => (
// eslint-disable-next-line react/jsx-key -- deuda conocida, ver SECURITY_DEBT.md #2, pendiente de fix
<SelectItem value={company.companyName}>
<SelectItem value={company.companyName} key={company._id}>
<span className="capitalize">
{company.companyName}
</span>
Expand Down
3 changes: 1 addition & 2 deletions components/datatableSeller1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,7 @@ export default function DataTableSeller1(props) {
<ScrollArea className="h-40">
<SelectItem value="">All</SelectItem>
{Allcompanies.map((company) => (
// eslint-disable-next-line react/jsx-key -- deuda conocida, ver SECURITY_DEBT.md #2, pendiente de fix
<SelectItem value={company.companyName}>
<SelectItem value={company.companyName} key={company._id}>
<span className="capitalize">{company.companyName}</span>
</SelectItem>
))}
Expand Down
Loading