Security Rules
9 rules that detect security vulnerabilities and unsafe patterns.
| Rule | Severity | What it catches |
|---|---|---|
no-hardcoded-secrets | error | API keys, tokens, passwords in source code |
no-eval | error | eval() or new Function() usage |
no-csrf-disabled | error | Explicitly disabling CSRF protection |
no-dangerous-redirects | error | Redirects with user-controlled input |
no-synchronize-in-production | error | synchronize: true in TypeORM config |
no-weak-crypto | warning | createHash('md5') or createHash('sha1') |
no-exposed-env-vars | warning | Direct process.env in Injectable/Controller |
no-exposed-stack-trace | warning | error.stack exposed in responses |
no-raw-entity-in-response | warning | Returning ORM entities directly from controllers |
no-hardcoded-secrets
Detects API keys, tokens, passwords, and other secrets hardcoded in source code.
Why: Secrets in source code end up in version control, CI logs, and npm packages. Use environment variables instead.
@Injectable()
export class AuthService {
private readonly apiKey = 'sk-1234567890abcdef';
private readonly dbPassword = 'super_secret_password';
}
no-eval
Detects eval() and new Function() usage which can execute arbitrary code.
Why: Both eval() and new Function() can execute arbitrary strings as code, enabling code injection attacks.
@Injectable()
export class CalcService {
evaluate(expression: string) {
return eval(expression);
}
}
no-csrf-disabled
Detects explicitly disabled CSRF protection.
Why: CSRF protection prevents cross-site request forgery attacks. Disabling it exposes your API to unauthorized actions from other sites.
app.use(csurf({ cookie: false }));
// or
const csrfOptions = { csrf: false };
no-dangerous-redirects
Detects redirects that use user-controlled input without validation.
Why: Open redirects allow attackers to redirect users to malicious sites using your domain as a trusted intermediary.
@Get('redirect')
redirect(@Query('url') url: string, @Res() res: Response) {
res.redirect(url);
}
no-synchronize-in-production
Detects synchronize: true in TypeORM configuration.
Why: synchronize: true auto-alters database schema to match entities on every app start. This can drop columns and tables in production, causing data loss.
TypeOrmModule.forRoot({
type: 'postgres',
synchronize: true,
})
no-weak-crypto
Detects usage of weak hashing algorithms (MD5, SHA-1).
Why: MD5 and SHA-1 are cryptographically broken. Use SHA-256 or stronger for any security-sensitive hashing.
import { createHash } from 'crypto';
const hash = createHash('md5').update(data).digest('hex');
no-exposed-env-vars
Detects direct process.env access in Injectable or Controller classes.
Why: Direct process.env access distributes configuration reads across the codebase, complicates testing, and bypasses NestJS's ConfigService validation.
@Injectable()
export class MailService {
private readonly apiKey = process.env.MAIL_API_KEY;
}
no-exposed-stack-trace
Detects error.stack being exposed in HTTP responses.
Why: Stack traces reveal internal file paths, dependency versions, and code structure to attackers.
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
catch(exception: Error, host: ArgumentsHost) {
response.json({ message: exception.message, stack: exception.stack });
}
}
no-raw-entity-in-response
Detects returning ORM entities directly from controller methods.
Why: ORM entities may contain internal fields (passwords, soft-delete flags, relation metadata) that should not be exposed. Use DTOs to control the response shape.
@Controller('users')
export class UserController {
@Get(':id')
findOne(@Param('id') id: string) {
return this.userRepo.findOne(id); // Returns raw entity
}
}