Hello,
I am investigating if and how hie files could be used for a cabal-audit command to check what are the declarations being used from the build dependencies. The use-case would be to alert the user when a vulnerable function is being used. This would be particularly important to avoid false alarm when a given vulnerability only appears in a rarely used declaration of a popular package.
So far, I’ve implemented the following function (code) which seems to work well for simple terms:
-- | Returns all the edges between a top level declaration and its dependencies.
getDependencies :: HieFile -> [(TopLevelDeclaration, Declaration)]
For example, given the following modules:
module CabalAudit.Test.Class where
class TestClass a where
tasty :: a -> Bool
module CabalAudit.Test.Instance where
import CabalAudit.Test.Class
data Tea = Tea
instance TestClass Tea where
tasty = not . alwaysTrue
instance Show Tea where
show Tea = "thè" ++ "!"
alwaysTrue :: Tea -> Bool
alwaysTrue = const True
module CabalAudit.Test.User where
import CabalAudit.Test.Class
import CabalAudit.Test.Instance
useAlwaysTrue :: Bool
useAlwaysTrue = tasty Tea
Here is the current output of the tool:
# CabalAudit.Test.Instance
GHC.Show.show: GHC.Base.++, CabalAudit.Test.Instance.Tea
CabalAudit.Test.Class.tasty: GHC.Base.., GHC.Classes.not, CabalAudit.Test.Instance.alwaysTrue, GHC.Base.const, GHC.Types.True
CabalAudit.Test.Instance.alwaysTrue: GHC.Base.const, GHC.Types.True
# CabalAudit.Test.User
CabalAudit.Test.User.useAlwaysTrue: CabalAudit.Test.Class.tasty, GHC.Base.., GHC.Classes.not, CabalAudit.Test.Instance.alwaysTrue, GHC.Base.const, GHC.Types.True, CabalAudit.Test.Instance.Tea
This looks promising, we can see that alwaysTrue
is reachable from the useAlwaysTrue
declaration. However, I don’t know why the class instances are not attached to the local module (e.g. CabalAudit.Test.Class.Show of Tea
instead of GHC.Show.show
).
Before continuing down that path, I would appreciate some feedbacks on this strategy, in particular:
- Is this a good usage of hie files? It seems like we would need to rebuild the dependencies with
-fwrite-ide-info
, so perhaps we could also use a GHC plugin, would that be better? - How to handle typeclass correctly, do we need to use generateReferencesMap?
- Beside typeclass instances, what other pitfalls would need to be addressed, e.g. are TypeFamilies going to be an issue?
Thank you for your time,
-Tristan