auditor

An aarch64 constant-time memory access auditing tool.
git clone git://git.ppad.tech/auditor.git
Log | Files | Refs | README | LICENSE

commit bfc4d70a9dd50b478247454e14b4757955316cd5
parent 2549b3e1c405920476b40f28a9f21d340a4d257f
Author: Jared Tobin <jared@jtobin.io>
Date:   Wed, 11 Feb 2026 22:03:02 +0400

feat: add --display-unknown flag to filter violation output

By default, only show secret violations (SecretBase, SecretIndex,
NonConstOffset). Unknown violations are hidden to reduce noise.

- Add -u/--display-unknown flag to show all violations
- Filter violations in both text and JSON output
- Show "(hidden): N unknown (use -u to show)" in summary when filtered

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Diffstat:
Mapp/Main.hs | 50++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 40 insertions(+), 10 deletions(-)

diff --git a/app/Main.hs b/app/Main.hs @@ -19,12 +19,13 @@ import Options.Applicative import System.Exit (exitFailure, exitSuccess) data Options = Options - { optInput :: !FilePath - , optJson :: !Bool - , optQuiet :: !Bool - , optInterProc :: !Bool - , optParseOnly :: !Bool - , optTaintConfig :: !(Maybe FilePath) + { optInput :: !FilePath + , optJson :: !Bool + , optQuiet :: !Bool + , optInterProc :: !Bool + , optParseOnly :: !Bool + , optTaintConfig :: !(Maybe FilePath) + , optDisplayUnknown :: !Bool } deriving (Eq, Show) optParser :: Parser Options @@ -60,6 +61,11 @@ optParser = Options <> metavar "FILE" <> help "JSON file with per-function taint policies" )) + <*> switch + ( long "display-unknown" + <> short 'u' + <> help "Display unknown violations (only secret shown by default)" + ) optInfo :: ParserInfo Options optInfo = info (optParser <**> helper) @@ -99,7 +105,7 @@ main = do exitFailure Right ar -> if optJson opts - then outputJson ar + then outputJson opts ar else outputText opts ar where emptyConfig = TaintConfig Map.empty @@ -112,12 +118,15 @@ main = do where hasConfig = not (Map.null (tcPolicies cfg)) -outputJson :: AuditResult -> IO () -outputJson ar = BL.putStrLn (encode (arViolations ar)) +outputJson :: Options -> AuditResult -> IO () +outputJson opts ar = + let vs = filterViolations opts (arViolations ar) + in BL.putStrLn (encode vs) outputText :: Options -> AuditResult -> IO () outputText opts ar = do - let vs = arViolations ar + let allVs = arViolations ar + vs = filterViolations opts allVs mapM_ printViolation vs if optQuiet opts then pure () @@ -126,10 +135,31 @@ outputText opts ar = do TIO.putStrLn $ "Lines checked: " <> T.pack (show (arLinesChecked ar)) TIO.putStrLn $ "Memory accesses: " <> T.pack (show (arMemoryAccesses ar)) TIO.putStrLn $ "Violations: " <> T.pack (show (length vs)) + if not (optDisplayUnknown opts) && length vs < length allVs + then TIO.putStrLn $ " (hidden): " + <> T.pack (show (length allVs - length vs)) + <> " unknown (use -u to show)" + else pure () if null vs then exitSuccess else exitFailure +-- | Filter violations based on options. +-- By default, only secret violations are shown. +filterViolations :: Options -> [Violation] -> [Violation] +filterViolations opts + | optDisplayUnknown opts = id + | otherwise = filter (isSecretViolation . vReason) + +-- | Check if a violation reason is secret (not unknown). +isSecretViolation :: ViolationReason -> Bool +isSecretViolation r = case r of + SecretBase _ -> True + SecretIndex _ -> True + UnknownBase _ -> False + UnknownIndex _ -> False + NonConstOffset -> True -- Treat as secret-level concern + printViolation :: Violation -> IO () printViolation v = TIO.putStrLn $ vSymbol v <> ":" <> T.pack (show (vLine v)) <> ": " <> reasonText (vReason v)