id: http-missing-security-headers

info:
  name: HTTP Missing Security Headers
  author: socketz,geeknik,G4L1T0,convisoappsec,kurohost,dawid-czarnecki,forgedhallpass,jub0bs,userdehghani,celbahraoui,safejulian
  severity: info
  description: |
    This template searches for missing HTTP security headers. The impact of these missing headers can vary.
  classification:
    cwe-id: CWE-693
  metadata:
    max-request: 1
  tags: misconfig,headers,generic,vuln

http:
  - method: GET
    path:
      - "{{BaseURL}}"

    host-redirects: true
    max-redirects: 3

    matchers-condition: or
    matchers:
      - type: dsl
        name: strict-transport-security
        dsl:
          - "!regex('(?i)strict-transport-security', header)"
          - "status_code != 301 && status_code != 302"
        condition: and

      - type: dsl
        name: content-security-policy
        dsl:
          - "!regex('(?i)content-security-policy', header)"
          - "status_code != 301 && status_code != 302"
        condition: and

      - type: dsl
        name: permissions-policy
        dsl:
          - "!regex('(?i)permissions-policy', header)"
          - "status_code != 301 && status_code != 302"
        condition: and

      - type: dsl
        name: x-frame-options
        dsl:
          - "!regex('(?i)x-frame-options', header)"
          - "status_code != 301 && status_code != 302"
        condition: and

      - type: dsl
        name: x-content-type-options
        dsl:
          - "!regex('(?i)x-content-type-options', header)"
          - "status_code != 301 && status_code != 302"
        condition: and

      - type: dsl
        name: x-permitted-cross-domain-policies
        dsl:
          - "!regex('(?i)x-permitted-cross-domain-policies', header)"
          - "status_code != 301 && status_code != 302"
        condition: and

      - type: dsl
        name: referrer-policy
        dsl:
          - "!regex('(?i)referrer-policy', header)"
          - "status_code != 301 && status_code != 302"
        condition: and

      - type: dsl
        name: cross-origin-embedder-policy
        dsl:
          - "!regex('(?i)cross-origin-embedder-policy', header)"
          - "status_code != 301 && status_code != 302"
        condition: and

      - type: dsl
        name: cross-origin-opener-policy
        dsl:
          - "!regex('(?i)cross-origin-opener-policy', header)"
          - "status_code != 301 && status_code != 302"
        condition: and

      - type: dsl
        name: cross-origin-resource-policy
        dsl:
          - "!regex('(?i)cross-origin-resource-policy', header)"
          - "status_code != 301 && status_code != 302"
        condition: and

      - type: dsl
        name: missing-content-type
        dsl:
          - "!regex('(?i)content-type:', header)"
          - "status_code == 200"
        condition: and

      - type: dsl
        name: content-type-charset-specification
        dsl:
          - "regex('(?i)content-type:\\s*text/html', header)"
          - "!regex('(?i)content-type:.*charset=', header)"
          - "status_code == 200"
        condition: and
# digest: 4b0a00483046022100de4b3a6468ef41ca1d8849f91bf21d9ba8a1d5eac12f93238dcfcbac9c2fa9ed022100fff99c6f6267833bc25981f3d2993bb01415ecac84be9eaee9dc1ab2e407f8fe:922c64590222798bb761d5b6d8e72950