Skip to content

Add security hint group - enabled by default#1681

Open
mgajda wants to merge 1 commit into
ndmitchell:masterfrom
mgajda:feature/security-rules
Open

Add security hint group - enabled by default#1681
mgajda wants to merge 1 commit into
ndmitchell:masterfrom
mgajda:feature/security-rules

Conversation

@mgajda
Copy link
Copy Markdown

@mgajda mgajda commented Apr 19, 2026

New group of security rules, enabled by default.

Currently catches two most common pitfalls:
read/reads on untrusted string, and use of obsolete hash functions.

LHS RHS Side CWE
read x Text.Read.readMaybe x not (isLitString x) CWE-502
reads x Text.Read.readMaybe x not (isLitString x) CWE-502
Crypto.Hash.MD5.hash Crypto.Hash.SHA256.hash CWE-327
Crypto.Hash.MD5.hashlazy Crypto.Hash.SHA256.hashlazy CWE-327
Crypto.Hash.SHA1.hash Crypto.Hash.SHA256.hash CWE-327
Crypto.Hash.SHA1.hashlazy Crypto.Hash.SHA256.hashlazy CWE-327
Data.Digest.Pure.MD5.md5 Crypto.Hash.SHA256.hashlazy CWE-327
Data.Digest.Pure.SHA.sha1 Data.Digest.Pure.SHA.sha256 CWE-327

Disable per-rule via -i "<name>" or suppress the whole group with - group: {name: security, enabled: false} in .hlint.yaml.

tests/security.test: four cases.

  1. security-hash.hs — all six hash rules fire.
  2. security-read-nonliteral.hsread x fires for variable x.
  3. security-read-literal.hsread "42" and read "3.14" do not fire.
  4. security-ignored.hs — per-rule -i suppression yields no hints.

Self-test: 974 tests, 3 failures (all pre-existing on master: issue #1674 intercalate/OverloadedStrings and two record-pattern type-application cases from PR #1680).

Running hlint with the new group on hlint's own source produces one finding: src/Test/InputOutput.hs:57 read code (parsing an EXIT line from a .test file).

No HSEC advisory on github.com/haskell/security-advisories maps to CWE-327 or CWE-502 for these function classes.

…untrusted input

data/hlint.yaml: new group 'security', enabled: true.

Rules:
  read  x -> Text.Read.readMaybe x   side: not (isLitString x)   CWE-502
  reads x -> Text.Read.readMaybe x   side: not (isLitString x)   CWE-502
  Crypto.Hash.MD5.hash      -> Crypto.Hash.SHA256.hash           CWE-327
  Crypto.Hash.MD5.hashlazy  -> Crypto.Hash.SHA256.hashlazy       CWE-327
  Crypto.Hash.SHA1.hash     -> Crypto.Hash.SHA256.hash           CWE-327
  Crypto.Hash.SHA1.hashlazy -> Crypto.Hash.SHA256.hashlazy       CWE-327
  Data.Digest.Pure.MD5.md5  -> Crypto.Hash.SHA256.hashlazy       CWE-327
  Data.Digest.Pure.SHA.sha1 -> Data.Digest.Pure.SHA.sha256       CWE-327

Disable per-rule via `-i "<name>"` or suppress the whole group with
`- group: {name: security, enabled: false}` in .hlint.yaml.

tests/security.test: four cases.
  1. security-hash.hs           : all six hash rules fire.
  2. security-read-nonliteral.hs: `read x` fires for variable `x`.
  3. security-read-literal.hs   : `read "42"` and `read "3.14"` do not fire.
  4. security-ignored.hs        : per-rule -i suppression yields no hints.

Self-test: 974 tests, 3 failures (all pre-existing on master: issue ndmitchell#1674
intercalate/OverloadedStrings and two record-pattern type-application
cases from PR ndmitchell#1680).

Running hlint with the new group on hlint's own source produces one
finding: src/Test/InputOutput.hs:57 `read code` (parsing an EXIT line
from a .test file).

No HSEC advisory on github.com/haskell/security-advisories maps to
CWE-327 or CWE-502 for these function classes.
@mgajda mgajda force-pushed the feature/security-rules branch from 3e34968 to 854c92d Compare April 19, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant