Skip to content

Commit ee35c14

Browse files
authored
Merge pull request #98 from Chrilleweb/cmn/dev
v2.3.9
2 parents ed9bfe3 + 84226c2 commit ee35c14

26 files changed

+851
-155
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ This project follows [Keep a Changelog](https://keepachangelog.com/) and [Semant
1212
### Fixed
1313
-
1414

15+
## [2.3.9] - 2025-12-09
16+
### Added
17+
- Added expiration date warnings for environment variables in codebase scanner.
18+
- Added inconsistent naming warnings for environment variables in codebase scanner.
19+
20+
### Changed
21+
- Changed health score calculation weights for better accuracy.
22+
- Removed CSP detection from codebase scanner, as it was causing false positives in some cases for backend frameworks.
23+
1524
## [2.3.8] - 2025-12-08
1625
### Added
1726
- Added variables not using uppercase letters warning to codebase scanner.

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,27 @@ The health score is calculated based on several factors, including:
145145
- Unused variables in your `.env` or `.env.example` file.
146146
- Framework specific warning for SvelteKit or Next.js (depending on detected framework).
147147

148+
## Expiration date warnings
149+
150+
By default, `dotenv-diff` will detect environment variables with expiration dates and warn you if they are expired or about to expire.
151+
To specify an expiration date for an environment variable, add a comment in the following format on the same line this an example of a .env.example file:
152+
153+
```bash
154+
# @expire YYYY-MM-DD
155+
API_TOKEN=
156+
```
157+
158+
When you run `dotenv-diff`, it will check the expiration dates and display warnings for any variables that are expired or will expire soon.
159+
160+
## Inconsistent naming pattern warnings
161+
162+
By default `dotenv-diff` will detect environment variables that have inconsistent naming patterns, fx `APIKEY` & `API_KEY` will give you are warning to only use the `API_KEY`
163+
To disable this behavior, use the `--no-inconsistent-naming-warnings` flags respectively, or set it to false in the config file:
164+
165+
```bash
166+
"inconsistentNamingWarnings": false
167+
```
168+
148169
## Show unused variables
149170

150171
As default, `dotenv-diff` will list variables that are defined in `.env` but never used in your codebase.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "dotenv-diff",
3-
"version": "2.3.8",
3+
"version": "2.3.9",
44
"type": "module",
55
"description": "Scan your codebase to find environment variables in use.",
66
"bin": {

src/cli/program.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,18 @@ export function createProgram() {
7272
'Enable uppercase key validation (enabled by default)',
7373
)
7474
.option('--no-uppercase-keys', 'Disable uppercase key validation')
75+
.option(
76+
'--expire-warnings',
77+
'Enable expiration date warnings for environment variables (enabled by default)',
78+
)
79+
.option('--no-expire-warnings', 'Disable expiration date warnings')
80+
.option(
81+
'--inconsistent-naming-warnings',
82+
'Enable inconsistent naming pattern warnings (enabled by default)',
83+
)
84+
.option(
85+
'--no-inconsistent-naming-warnings',
86+
'Disable inconsistent naming pattern warnings',
87+
)
7588
.option('--init', 'Create a sample dotenv-diff.config.json file');
7689
}

src/cli/run.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ async function runScanMode(opts: Options): Promise<void> {
4343
ignoreUrls: opts.ignoreUrls ?? [],
4444
noCompare: opts.noCompare ?? false,
4545
uppercaseKeys: opts.uppercaseKeys ?? true,
46+
expireWarnings: opts.expireWarnings,
47+
inconsistentNamingWarnings: opts.inconsistentNamingWarnings,
4648
...(opts.files ? { files: opts.files } : {}),
4749
});
4850

src/commands/scanUsage.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import { printComparisonError } from '../ui/scan/printComparisonError.js';
1313
import { hasIgnoreComment } from '../core/secretDetectors.js';
1414
import { frameworkValidator } from '../core/frameworkValidator.js';
1515
import { detectSecretsInExample } from '../core/exampleSecretDetector.js';
16-
import { detectUppercaseKeys } from '../core/detectUppercaseKeys.js';
1716

1817
/**
1918
* Filters out commented usages from the list.
@@ -126,10 +125,6 @@ export async function scanUsage(
126125
scanResult.frameworkWarnings = frameworkWarnings;
127126
}
128127

129-
if (opts.uppercaseKeys) {
130-
scanResult.uppercaseWarnings = detectUppercaseKeys(scanResult.used);
131-
}
132-
133128
// Determine which file to compare against
134129
const compareFile = determineComparisonFile(opts);
135130
let envVariables: Record<string, string | undefined> = {};
@@ -166,6 +161,13 @@ export async function scanUsage(
166161
if (result.uppercaseWarnings) {
167162
scanResult.uppercaseWarnings = result.uppercaseWarnings;
168163
}
164+
if (result.expireWarnings) {
165+
scanResult.expireWarnings = result.expireWarnings;
166+
}
167+
if (result.inconsistentNamingWarnings) {
168+
scanResult.inconsistentNamingWarnings =
169+
result.inconsistentNamingWarnings;
170+
}
169171
if (result.exampleFull && result.comparedAgainst === '.env.example') {
170172
scanResult.exampleWarnings = detectSecretsInExample(result.exampleFull);
171173
}
@@ -207,7 +209,9 @@ export async function scanUsage(
207209
(scanResult.exampleWarnings?.length ?? 0) > 0 ||
208210
(scanResult.frameworkWarnings?.length ?? 0) > 0 ||
209211
(scanResult.logged?.length ?? 0) > 0 ||
210-
(scanResult.uppercaseWarnings?.length ?? 0) > 0
212+
(scanResult.uppercaseWarnings?.length ?? 0) > 0 ||
213+
(scanResult.expireWarnings?.length ?? 0) > 0 ||
214+
(scanResult.inconsistentNamingWarnings?.length ?? 0) > 0
211215
),
212216
};
213217
}

src/config/options.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ export function normalizeOptions(raw: RawOptions): Options {
100100

101101
const ignoreUrls = parseList(raw.ignoreUrls);
102102
const uppercaseKeys = raw.uppercaseKeys !== false;
103+
const expireWarnings = raw.expireWarnings !== false;
104+
const inconsistentNamingWarnings = raw.inconsistentNamingWarnings !== false;
103105

104106
const cwd = process.cwd();
105107
const envFlag =
@@ -139,5 +141,7 @@ export function normalizeOptions(raw: RawOptions): Options {
139141
ignoreUrls,
140142
noCompare,
141143
uppercaseKeys,
144+
expireWarnings,
145+
inconsistentNamingWarnings,
142146
};
143147
}

src/config/types.ts

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ export type Options = {
5353
ignoreUrls?: string[];
5454
noCompare: boolean;
5555
uppercaseKeys: boolean;
56+
expireWarnings: boolean;
57+
inconsistentNamingWarnings: boolean;
5658
};
5759

5860
/** Type representing the raw options for the comparison
@@ -84,6 +86,8 @@ export type RawOptions = {
8486
noCompare?: boolean;
8587
init?: boolean;
8688
uppercaseKeys?: boolean;
89+
expireWarnings?: boolean;
90+
inconsistentNamingWarnings?: boolean;
8791
};
8892

8993
/**
@@ -153,11 +157,12 @@ export interface ScanResult {
153157
env?: Array<{ key: string; count: number }>;
154158
example?: Array<{ key: string; count: number }>;
155159
};
156-
hasCsp?: boolean;
157160
frameworkWarnings?: frameworkWarning[];
158161
exampleWarnings?: ExampleSecretWarning[];
159162
logged: EnvUsage[];
160163
uppercaseWarnings?: UppercaseWarning[];
164+
expireWarnings?: ExpireWarning[];
165+
inconsistentNamingWarnings?: InconsistentNamingWarning[];
161166
}
162167

163168
/** Options for scanning the codebase for environment variable usage. */
@@ -173,6 +178,8 @@ export interface ScanUsageOptions extends ScanOptions {
173178
allowDuplicates?: boolean;
174179
strict?: boolean;
175180
uppercaseKeys?: boolean;
181+
expireWarnings?: boolean;
182+
inconsistentNamingWarnings?: boolean;
176183
}
177184

178185
export interface ScanJsonEntry {
@@ -212,13 +219,26 @@ export interface ScanJsonEntry {
212219
env?: Array<{ key: string; count: number }>;
213220
example?: Array<{ key: string; count: number }>;
214221
};
215-
hasCsp?: boolean;
216222
logged?: Array<{
217223
variable: string;
218224
file: string;
219225
line: number;
220226
context: string;
221227
}>;
228+
expireWarnings?: Array<{
229+
key: string;
230+
date: string;
231+
daysLeft: number;
232+
}>;
233+
uppercaseWarnings?: Array<{
234+
key: string;
235+
suggestion: string;
236+
}>;
237+
inconsistentNamingWarnings?: Array<{
238+
key1: string;
239+
key2: string;
240+
suggestion: string;
241+
}>;
222242
}
223243

224244
// Type for grouped usages by variable
@@ -239,6 +259,8 @@ export interface ComparisonOptions {
239259
showStats?: boolean;
240260
strict?: boolean;
241261
uppercaseKeys?: boolean;
262+
expireWarnings?: boolean;
263+
inconsistentNamingWarnings?: boolean;
242264
}
243265

244266
export interface FilePair {
@@ -279,3 +301,15 @@ export interface UppercaseWarning {
279301
key: string;
280302
suggestion: string;
281303
}
304+
305+
export interface ExpireWarning {
306+
key: string;
307+
date: string;
308+
daysLeft: number;
309+
}
310+
311+
export interface InconsistentNamingWarning {
312+
key1: string;
313+
key2: string;
314+
suggestion: string;
315+
}

src/core/computeHealthScore.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,30 @@ export function computeHealthScore(scan: ScanResult): number {
1212
const highSecrets = scan.secrets?.filter((s) => s.severity === 'high') ?? [];
1313
const medSecrets = scan.secrets?.filter((s) => s.severity === 'medium') ?? [];
1414

15-
score -= highSecrets.length * 15;
16-
score -= medSecrets.length * 5;
15+
score -= highSecrets.length * 20;
16+
score -= medSecrets.length * 10;
1717

1818
// === 2. Missing environment variables ===
19-
score -= scan.missing.length * 5;
19+
score -= scan.missing.length * 20;
2020

2121
// === 3. Uppercase naming issues ===
2222
score -= (scan.uppercaseWarnings?.length ?? 0) * 2;
2323

2424
// === 4. Console logging ===
25-
score -= (scan.logged?.length ?? 0) * 5;
25+
score -= (scan.logged?.length ?? 0) * 10;
2626

2727
// === 5. Unused vars (less important) ===
2828
score -= (scan.unused?.length ?? 0) * 1;
2929

3030
// === 6. Framework warnings ===
31-
score -= (scan.frameworkWarnings?.length ?? 0) * 2;
31+
score -= (scan.frameworkWarnings?.length ?? 0) * 5;
3232

3333
// === 7. Example secrets ===
3434
score -= (scan.exampleWarnings?.length ?? 0) * 10;
3535

36+
// === 8. Expiration warnings ===
37+
score -= (scan.expireWarnings?.length ?? 0) * 5;
38+
3639
// Never go below 0 or above 100
3740
return Math.max(0, Math.min(100, score));
3841
}

src/core/cspDetector.ts

Lines changed: 0 additions & 40 deletions
This file was deleted.

0 commit comments

Comments
 (0)