rules:
  - id: auth.nestjs.jwt-hardcoded-secret
    languages:
      - javascript
      - typescript
    severity: ERROR
    message: |
      A NestJS `JwtModule` is configured with a hard-coded `secret` (or
      `secretOrPrivateKey`) string literal. This key signs and verifies every
      access token: committed to git it is one search away from compromise,
      letting an attacker forge tokens for any user.

      Read it from the environment instead. Use `JwtModule.registerAsync` with
      `ConfigService` (`useFactory: (config) => ({ secret: config.get('JWT_SECRET') })`)
      or `secret: process.env.JWT_SECRET`, and add the variable to `.env.example`
      with a placeholder. Rotate the leaked value out of source control.
    # Anchored to a `JwtModule.register(...)` / `JwtModule.registerAsync(...)`
    # call so a bare `secret:` in unrelated config never fires. The value must
    # be an AST string literal, so `process.env.*` reads and `config.get(...)`
    # calls are structurally excluded; the regex allow-list drops `${ENV}`
    # templates, `<placeholders>`, and obvious doc/test stubs. `paths.exclude`
    # keeps the rule off test/example trees where a throwaway dev secret is
    # intentional.
    patterns:
      - pattern-either:
          - pattern: 'secret: "..."'
          - pattern: 'secretOrPrivateKey: "..."'
      - pattern-not-regex: |-
          (?i)(?:secret|secretOrPrivateKey)\s*:\s*['"]\$\{?[A-Za-z_]+\}?['"]
      - pattern-not-regex: |-
          (?i)(?:secret|secretOrPrivateKey)\s*:\s*['"]<[^'"]*>['"]
      - pattern-not-regex: |-
          (?i)(?:secret|secretOrPrivateKey)\s*:\s*['"](?:your[-_]|my[-_]|example|placeholder|xxx+|todo|fixme|test|dummy|fake|sample|changeme|change[-_]?me|redacted|replace)
      - pattern-either:
          - pattern-inside: 'JwtModule.register({...})'
          - pattern-inside: 'JwtModule.registerAsync({...})'
          - pattern-inside: 'new JwtService({...})'
    paths:
      exclude:
        - "**/test/**"
        - "**/__tests__/**"
        - "**/*.test.*"
        - "**/*.spec.*"
        - "**/example/**"
        - "**/examples/**"
        - "**/demo/**"
        - "**/benchmark/**"
        - "**/benchmarks/**"
        - "**/integration/**"
        - "**/*.tst.*"
    metadata:
      oauthlint-rule-id: AUTH-NESTJS-001
      oauthlint-doc-url: https://oauthlint.dev/rules/nestjs-jwt-hardcoded-secret
      category: security
      cwe: CWE-798
      owasp: API2:2023
      llm-prevalence: HIGH
      technology:
        - nestjs
        - "@nestjs/jwt"
      references:
        - https://docs.nestjs.com/security/authentication
        - https://cwe.mitre.org/data/definitions/798.html
