diff --git a/pkg/render/markdown.go b/pkg/render/markdown.go
index ae8c38c63..edd9caa61 100644
--- a/pkg/render/markdown.go
+++ b/pkg/render/markdown.go
@@ -73,22 +73,6 @@ func (r Markdown) Full(ctx context.Context, rep *malcontent.Report) error {
}
for modified := rep.Diff.Modified.Oldest(); modified != nil; modified = modified.Next() {
- var title string
- if modified.Value.PreviousRelPath != "" && modified.Value.PreviousRelPathScore >= 0.9 {
- title = fmt.Sprintf("## Moved: %s -> %s (similarity: %0.2f)", modified.Value.PreviousPath, modified.Value.Path, modified.Value.PreviousRelPathScore)
- } else {
- title = fmt.Sprintf("## Changed: %s", modified.Value.Path)
- }
- if modified.Value.RiskScore != modified.Value.PreviousRiskScore {
- title = fmt.Sprintf("%s [%s → %s]",
- title,
- mdRisk(modified.Value.PreviousRiskScore, modified.Value.PreviousRiskLevel),
- mdRisk(modified.Value.RiskScore, modified.Value.RiskLevel))
- }
-
- if len(modified.Value.Behaviors) > 0 {
- fmt.Fprint(r.w, title+"\n\n")
- }
added := 0
removed := 0
noDiff := 0
@@ -104,6 +88,29 @@ func (r Markdown) Full(ctx context.Context, rep *malcontent.Report) error {
}
}
+ if added == 0 && removed == 0 {
+ continue
+ }
+
+ var title string
+ switch {
+ case modified.Value.PreviousRelPath != "" && modified.Value.PreviousRelPathScore >= 0.9:
+ title = fmt.Sprintf("## Moved: %s -> %s (similarity: %0.2f)", modified.Value.PreviousPath, modified.Value.Path, modified.Value.PreviousRelPathScore)
+ default:
+ title = fmt.Sprintf("## Changed (%d added, %d removed): %s", added, removed, modified.Value.Path)
+ }
+
+ if modified.Value.RiskScore != modified.Value.PreviousRiskScore {
+ title = fmt.Sprintf("%s [%s → %s]",
+ title,
+ mdRisk(modified.Value.PreviousRiskScore, modified.Value.PreviousRiskLevel),
+ mdRisk(modified.Value.RiskScore, modified.Value.RiskLevel))
+ }
+
+ if len(modified.Value.Behaviors) > 0 {
+ fmt.Fprint(r.w, title+"\n\n")
+ }
+
// We split the added/removed up in Markdown to address readability feedback. Unfortunately,
// this means we hide "existing" behaviors, which causes context to suffer. We should evaluate an
// improved rendering, similar to the "terminal" refresh, that includes everything.
@@ -140,17 +147,7 @@ func (r Markdown) Full(ctx context.Context, rep *malcontent.Report) error {
}
if noDiff > 0 {
- count = noDiff
- noun := "behavior"
- qual = "consistent"
- if count > 1 {
- noun = "behaviors"
- }
- markdownTable(ctx, modified.Value, r.w, tableConfig{
- Title: fmt.Sprintf("### %d %s %s", count, qual, noun),
- SkipAdded: true,
- SkipRemoved: true,
- })
+ continue
}
}
return nil
diff --git a/pkg/render/simple.go b/pkg/render/simple.go
index ec3093c0b..7877635e0 100644
--- a/pkg/render/simple.go
+++ b/pkg/render/simple.go
@@ -83,11 +83,23 @@ func (r Simple) Full(_ context.Context, rep *malcontent.Report) error {
}
}
+ count := func(bs []*malcontent.Behavior) (int, int) {
+ var added, removed int
+ for _, b := range bs {
+ if b.DiffAdded {
+ added++
+ }
+ if b.DiffRemoved {
+ removed++
+ }
+ }
+
+ return added, removed
+ }
+
for modified := rep.Diff.Modified.Oldest(); modified != nil; modified = modified.Next() {
if modified.Value.PreviousRelPath != "" && modified.Value.PreviousRelPathScore >= 0.9 {
fmt.Fprintf(r.w, ">>> moved: %s -> %s (score: %f)\n", modified.Value.PreviousPath, modified.Value.Path, modified.Value.PreviousRelPathScore)
- } else {
- fmt.Fprintf(r.w, "*** changed: %s\n", modified.Value.Path)
}
var bs []*malcontent.Behavior
@@ -97,8 +109,14 @@ func (r Simple) Full(_ context.Context, rep *malcontent.Report) error {
return bs[i].ID < bs[j].ID
})
- for i := range bs {
- b := bs[i]
+ added, removed := count(bs)
+ if added == 0 && removed == 0 {
+ continue
+ }
+
+ fmt.Fprintf(r.w, "*** changed (%d added, %d removed): %s\n", added, removed, modified.Value.Path)
+
+ for _, b := range bs {
if b.DiffRemoved {
fmt.Fprintf(r.w, "-%s\n", b.ID)
continue
@@ -107,7 +125,7 @@ func (r Simple) Full(_ context.Context, rep *malcontent.Report) error {
fmt.Fprintf(r.w, "+%s\n", b.ID)
}
if !b.DiffRemoved && !b.DiffAdded {
- fmt.Fprintf(r.w, "%s\n", b.ID)
+ continue
}
}
}
diff --git a/pkg/render/tea_style.go b/pkg/render/tea_style.go
index 7d928c187..7b36a141e 100644
--- a/pkg/render/tea_style.go
+++ b/pkg/render/tea_style.go
@@ -60,9 +60,6 @@ var (
diffRemovedStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("196"))
-
- diffUnchangedStyle = lipgloss.NewStyle().
- Foreground(lipgloss.Color("69"))
)
// cleanAndWrapEvidence handles evidence strings, including those with escape sequences.
@@ -135,6 +132,7 @@ func renderFileSummaryTea(_ context.Context, fr *malcontent.FileReport, w io.Wri
previousNsRiskScore := map[string]int{}
diffMode := false
+ var added, removed int
for _, b := range fr.Behaviors {
ns, _ := splitRuleID(b.ID)
if b.DiffAdded || b.DiffRemoved {
@@ -147,6 +145,13 @@ func renderFileSummaryTea(_ context.Context, fr *malcontent.FileReport, w io.Wri
if !b.DiffRemoved && b.RiskScore > nsRiskScore[ns] {
nsRiskScore[ns] = b.RiskScore
}
+
+ if b.DiffAdded {
+ added++
+ }
+ if b.DiffRemoved {
+ removed++
+ }
}
// Sort namespaces
@@ -176,7 +181,12 @@ func renderFileSummaryTea(_ context.Context, fr *malcontent.FileReport, w io.Wri
riskBadge,
)
+ if added == 0 && removed == 0 {
+ return
+ }
+
if diffMode {
+ rc.Title = fmt.Sprintf("Changed (%d added, %d removed): %s", added, removed, fr.Path)
header = lipgloss.JoinHorizontal(
lipgloss.Center,
pathStyle.Render(rc.Title),
@@ -245,8 +255,7 @@ func renderFileSummaryTea(_ context.Context, fr *malcontent.FileReport, w io.Wri
baseStyle = diffRemovedStyle
e = ""
default:
- baseStyle = diffUnchangedStyle
- e = ""
+ continue
}
}
diff --git a/pkg/render/terminal.go b/pkg/render/terminal.go
index c330c89cf..cddacbf9d 100644
--- a/pkg/render/terminal.go
+++ b/pkg/render/terminal.go
@@ -116,10 +116,7 @@ func (r Terminal) Full(ctx context.Context, rep *malcontent.Report) error {
var title string
if modified.Value.PreviousRelPath != "" && modified.Value.PreviousRelPathScore >= 0.9 {
title = fmt.Sprintf("Moved: %s -> %s (score: %f)", modified.Value.PreviousPath, modified.Value.Path, modified.Value.PreviousRelPathScore)
- } else {
- title = fmt.Sprintf("Changed: %s", modified.Value.Path)
}
-
if modified.Value.RiskScore != modified.Value.PreviousRiskScore {
title = fmt.Sprintf("%s %s", title,
darkBrackets(fmt.Sprintf("%s %s %s", riskInColor(modified.Value.PreviousRiskLevel), color.HiWhiteString("→"), riskInColor(modified.Value.RiskLevel))))
@@ -220,7 +217,6 @@ func ansiLineLength(s string) int {
}
func renderFileSummary(_ context.Context, fr *malcontent.FileReport, w io.Writer, rc tableConfig) {
- fmt.Fprintf(w, "├─ %s %s\n", riskEmoji(fr.RiskScore), rc.Title)
width := suggestedWidth()
byNamespace := map[string][]*malcontent.Behavior{}
@@ -232,6 +228,7 @@ func renderFileSummary(_ context.Context, fr *malcontent.FileReport, w io.Writer
return
}
+ var added, removed int
for _, b := range fr.Behaviors {
ns, _ := splitRuleID(b.ID)
@@ -247,15 +244,28 @@ func renderFileSummary(_ context.Context, fr *malcontent.FileReport, w io.Writer
byNamespace[ns] = append(byNamespace[ns], b)
+ if b.DiffAdded {
+ added++
+ }
if b.DiffRemoved {
- continue
+ removed++
}
if b.RiskScore > nsRiskScore[ns] {
nsRiskScore[ns] = b.RiskScore
}
+
+ if added == 0 && removed == 0 {
+ continue
+ }
+
+ if diffMode {
+ rc.Title = fmt.Sprintf("Changed (%d added, %d removed): %s", added, removed, fr.Path)
+ }
}
+ fmt.Fprintf(w, "├─ %s %s\n", riskEmoji(fr.RiskScore), rc.Title)
+
nss := []string{}
for ns := range byNamespace {
nss = append(nss, ns)
@@ -281,10 +291,10 @@ func renderFileSummary(_ context.Context, fr *malcontent.FileReport, w io.Writer
diff = color.HiGreenString("+")
}
- if riskLevel < previousRiskLevel {
+ if riskScore > previousNsRiskScore[ns] {
nsIcon = color.HiYellowString("▲")
}
- if riskLevel > previousRiskLevel {
+ if riskScore < previousNsRiskScore[ns] {
nsIcon = color.HiGreenString("▼")
}
if riskLevel == "NONE" {
@@ -331,8 +341,7 @@ func renderFileSummary(_ context.Context, fr *malcontent.FileReport, w io.Writer
}
if !b.DiffAdded && !b.DiffRemoved {
- pc = color.New(color.FgHiCyan)
- e = ""
+ continue
}
content = fmt.Sprintf("%s%s%s %s %s", diff, indent, bullet, rest, desc)
diff --git a/tests/javascript/2024.lottie-player/lottie-player.min.js.mdiff b/tests/javascript/2024.lottie-player/lottie-player.min.js.mdiff
index 1f771890d..06923a73a 100644
--- a/tests/javascript/2024.lottie-player/lottie-player.min.js.mdiff
+++ b/tests/javascript/2024.lottie-player/lottie-player.min.js.mdiff
@@ -1,4 +1,4 @@
-## Changed: javascript/2024.lottie-player/lottie-player.min.js [🟡 MEDIUM → 😈 CRITICAL]
+## Changed (49 added, 2 removed): javascript/2024.lottie-player/lottie-player.min.js [🟡 MEDIUM → 😈 CRITICAL]
### 49 new behaviors
@@ -61,14 +61,3 @@
| -MEDIUM | [exec/remote_commands/code_eval](https://github.com/chainguard-dev/malcontent/blob/main/rules/exec/remote_commands/code_eval.yara#eval) | evaluate code dynamically using eval() | [eval("](https://github.com/search?q=eval%28%22&type=code) |
| -MEDIUM | [os/time/clock_sleep](https://github.com/chainguard-dev/malcontent/blob/main/rules/os/time/clock-sleep.yara#setInterval) | uses setInterval to wait | [setInterval(](https://github.com/search?q=setInterval%28&type=code) |
-### 6 consistent behaviors
-
-| RISK | KEY | DESCRIPTION | EVIDENCE |
-|--|--|--|--|
-| MEDIUM | [net/download](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/download/download.yara#download) | download files | [Downloads](https://github.com/search?q=Downloads&type=code)
[downloads-view](https://github.com/search?q=downloads-view&type=code)
[mobile-download-links](https://github.com/search?q=mobile-download-links&type=code) |
-| LOW | [data/encoding/json_decode](https://github.com/chainguard-dev/malcontent/blob/main/rules/data/encoding/json-decode.yara#jsondecode) | Decodes JSON messages | [JSON.parse](https://github.com/search?q=JSON.parse&type=code) |
-| LOW | [data/encoding/json_encode](https://github.com/chainguard-dev/malcontent/blob/main/rules/data/encoding/json-encode.yara#JSONEncode) | encodes JSON | [JSON.stringify](https://github.com/search?q=JSON.stringify&type=code) |
-| LOW | [exec/plugin](https://github.com/chainguard-dev/malcontent/blob/main/rules/exec/plugin/plugin.yara#plugin) | references a 'plugin' | [plugin_relativeTime](https://github.com/search?q=plugin_relativeTime&type=code)
[plugin_updateLocale](https://github.com/search?q=plugin_updateLocale&type=code)
[plugins](https://github.com/search?q=plugins&type=code) |
-| LOW | [net/url/embedded](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/url/embedded.yara#https_url) | contains embedded HTTPS URLs | [https://abitype.dev](https://abitype.dev)
[https://andromeda-explorer.metis.io/api](https://andromeda-explorer.metis.io/api)
[https://andromeda.metis.io/?owner=1088](https://andromeda.metis.io/?owner=1088)
[https://api-era.zksync.network/api](https://api-era.zksync.network/api)
[https://api-moonbeam.moonscan.io/api](https://api-moonbeam.moonscan.io/api)
[https://api-moonriver.moonscan.io/api](https://api-moonriver.moonscan.io/api)
[https://api-optimistic.etherscan.io/api](https://api-optimistic.etherscan.io/api)
[https://api-zkevm.polygonscan.com/api](https://api-zkevm.polygonscan.com/api)
[https://api.arbiscan.io/api](https://api.arbiscan.io/api)
[https://api.avax.network/ext/bc/C/rpc](https://api.avax.network/ext/bc/C/rpc)
[https://api.basescan.org/api](https://api.basescan.org/api)
[https://api.blastscan.io/api](https://api.blastscan.io/api)
[https://api.bscscan.com/api](https://api.bscscan.com/api)
[https://api.celoscan.io/api](https://api.celoscan.io/api)
[https://api.etherscan.io/api](https://api.etherscan.io/api)
[https://api.ftmscan.com/api](https://api.ftmscan.com/api)
[https://api.gnosisscan.io/api](https://api.gnosisscan.io/api)
[https://api.lineascan.build/api](https://api.lineascan.build/api)
[https://api.mantlescan.xyz/api](https://api.mantlescan.xyz/api)
[https://api.polygonscan.com/api](https://api.polygonscan.com/api)
[https://api.roninchain.com/rpc](https://api.roninchain.com/rpc)
[https://api.routescan.io/v2/network/mainnet/evm/43114/etherscan/api](https://api.routescan.io/v2/network/mainnet/evm/43114/etherscan/api)
[https://api.scan.pulsechain.com/api](https://api.scan.pulsechain.com/api)
[https://api.scrollscan.com/api](https://api.scrollscan.com/api)
[https://api.snowtrace.io](https://api.snowtrace.io)
[https://api.wallet.coinbase.com/rpc/v2/desktop/chrome](https://api.wallet.coinbase.com/rpc/v2/desktop/chrome)
[https://api.web3modal.org](https://api.web3modal.org)
[https://app.roninchain.com](https://app.roninchain.com)
[https://arb1.arbitrum.io/rpc](https://arb1.arbitrum.io/rpc)
[https://arbiscan.io](https://arbiscan.io)
[https://arweave.net](https://arweave.net)
[https://aurorascan.dev/api](https://aurorascan.dev/api)
[https://avatar.vercel.sh/andrew.svg?size=50](https://avatar.vercel.sh/andrew.svg?size=50)
[https://basescan.org](https://basescan.org)
[https://blastscan.io](https://blastscan.io)
[https://block-explorer-api.mainnet.zksync.io/api](https://block-explorer-api.mainnet.zksync.io/api)
[https://bobascan.com](https://bobascan.com)
[https://bscscan.com](https://bscscan.com)
[https://build.onbeam.com/rpc](https://build.onbeam.com/rpc)
[https://celoscan.io](https://celoscan.io)
[https://cloudflare-eth.com](https://cloudflare-eth.com)
[https://docs.cloud.coinbase.com/wallet-sdk/docs/errors](https://docs.cloud.coinbase.com/wallet-sdk/docs/errors)
[https://docs.soliditylang.org/en/latest/cheatsheet.html](https://docs.soliditylang.org/en/latest/cheatsheet.html)
[https://echo.walletconnect.com/](https://echo.walletconnect.com/)
[https://era.zksync.network/](https://era.zksync.network/)
[https://ethereum.org/en/developers/docs/networks/](https://ethereum.org/en/developers/docs/networks/)
[https://etherscan.io](https://etherscan.io)
[https://evm.cronos.org](https://evm.cronos.org)
[https://evm.kava.io](https://evm.kava.io)
[https://exchainrpc.okex.org](https://exchainrpc.okex.org)
[https://explorer-api.cronos.org/mainnet/api](https://explorer-api.cronos.org/mainnet/api)
[https://explorer-api.walletconnect.com](https://explorer-api.walletconnect.com)
[https://explorer.cronos.org](https://explorer.cronos.org)
[https://explorer.dogechain.dog/api](https://explorer.dogechain.dog/api)
[https://explorer.fuse.io/api](https://explorer.fuse.io/api)
[https://explorer.harmony.one](https://explorer.harmony.one)
[https://explorer.kcc.io](https://explorer.kcc.io)
[https://explorer.metis.io](https://explorer.metis.io)
[https://explorer.walletconnect.com/?type=wallet](https://explorer.walletconnect.com/?type=wallet)
[https://explorer.zksync.io/](https://explorer.zksync.io/)
[https://fonts.googleapis.com/css2?family=Inter](https://fonts.googleapis.com/css2?family=Inter)
[https://forno.celo.org](https://forno.celo.org)
[https://ftmscan.com](https://ftmscan.com)
[https://gnosisscan.io](https://gnosisscan.io)
[https://go.cb-w.com/dapp?cb_url=](https://go.cb-w.com/dapp?cb_url=)
[https://go.cb-w.com/walletlink](https://go.cb-w.com/walletlink)
[https://kavascan.com/api](https://kavascan.com/api)
[https://kcc-rpc.com](https://kcc-rpc.com)
[https://keys.coinbase.com/connect](https://keys.coinbase.com/connect)
[https://lineascan.build](https://lineascan.build)
[https://links.ethers.org/v5-errors-](https://links.ethers.org/v5-errors-)
[https://mainnet.aurora.dev](https://mainnet.aurora.dev)
[https://mainnet.base.org](https://mainnet.base.org)
[https://mainnet.boba.network](https://mainnet.boba.network)
[https://mainnet.era.zksync.io](https://mainnet.era.zksync.io)
[https://mainnet.optimism.io](https://mainnet.optimism.io)
[https://mantlescan.xyz/](https://mantlescan.xyz/)
[https://moonbeam.public.blastapi.io](https://moonbeam.public.blastapi.io)
[https://moonriver.moonscan.io](https://moonriver.moonscan.io)
[https://moonriver.public.blastapi.io](https://moonriver.public.blastapi.io)
[https://moonscan.io](https://moonscan.io)
[https://npms.io/search?q=ponyfill.](https://npms.io/search?q=ponyfill.)
[https://openchain.xyz/signatures?query=](https://openchain.xyz/signatures?query=)
[https://optimistic.etherscan.io](https://optimistic.etherscan.io)
[https://polygon-rpc.com](https://polygon-rpc.com)
[https://polygonscan.com](https://polygonscan.com)
[https://pulse.walletconnect.org](https://pulse.walletconnect.org)
[https://reactjs.org/docs/error-decoder.html?invariant=](https://reactjs.org/docs/error-decoder.html?invariant=)
[https://rpc.ankr.com/bsc](https://rpc.ankr.com/bsc)
[https://rpc.ankr.com/fantom](https://rpc.ankr.com/fantom)
[https://rpc.ankr.com/harmony](https://rpc.ankr.com/harmony)
[https://rpc.blast.io](https://rpc.blast.io)
[https://rpc.dogechain.dog](https://rpc.dogechain.dog)
[https://rpc.fuse.io](https://rpc.fuse.io)
[https://rpc.gnosischain.com](https://rpc.gnosischain.com)
[https://rpc.linea.build](https://rpc.linea.build)
[https://rpc.mantle.xyz](https://rpc.mantle.xyz)
[https://rpc.pulsechain.com](https://rpc.pulsechain.com)
[https://rpc.scroll.io](https://rpc.scroll.io)
[https://rpc.walletconnect.com/v1/?chainId=eip155](https://rpc.walletconnect.com/v1/?chainId=eip155)
[https://rpc.walletconnect.org](https://rpc.walletconnect.org)
[https://safe-client.safe.global](https://safe-client.safe.global)
[https://scan.pulsechain.com](https://scan.pulsechain.com)
[https://scrollscan.com](https://scrollscan.com)
[https://secure.walletconnect.org/sdk](https://secure.walletconnect.org/sdk)
[https://snowtrace.io](https://snowtrace.io)
[https://subnets.avax.network/beam](https://subnets.avax.network/beam)
[https://verify.walletconnect.com](https://verify.walletconnect.com)
[https://verify.walletconnect.org](https://verify.walletconnect.org)
[https://wagmi.sh/core](https://wagmi.sh/core)
[https://wagmi.sh/react](https://wagmi.sh/react)
[https://walletconnect.com/explorer?type=wallet](https://walletconnect.com/explorer?type=wallet)
[https://walletconnect.com/faq](https://walletconnect.com/faq)
[https://www.jsdelivr.com/using-sri-with-dynamic-files](https://www.jsdelivr.com/using-sri-with-dynamic-files)
[https://www.oklink.com/okc](https://www.oklink.com/okc)
[https://www.walletlink.org](https://www.walletlink.org)
[https://zkevm-rpc.com](https://zkevm-rpc.com)
[https://zkevm.polygonscan.com](https://zkevm.polygonscan.com) |
-| LOW | [net/url/parse](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/url/parse.yara#url_handle) | Handles URL strings | [new URL](https://github.com/search?q=new+URL&type=code) |
-
diff --git a/tests/linux/2023.FreeDownloadManager/freedownloadmanager.sdiff b/tests/linux/2023.FreeDownloadManager/freedownloadmanager.sdiff
index e8f95c63b..686b25827 100644
--- a/tests/linux/2023.FreeDownloadManager/freedownloadmanager.sdiff
+++ b/tests/linux/2023.FreeDownloadManager/freedownloadmanager.sdiff
@@ -1,30 +1,22 @@
-*** changed: linux/2023.FreeDownloadManager/freedownloadmanager_infected_postinst
+*** changed (20 added, 1 removed): linux/2023.FreeDownloadManager/freedownloadmanager_infected_postinst
+anti-static/base64/exec
+anti-static/base64/http_agent
-c2/tool_transfer/arch
-c2/tool_transfer/os
+data/base64/external
+data/embedded/base64_elf
+data/embedded/base64_terms
+data/embedded/base64_url
-data/embedded/pgp_key
+data/encoding/base64
+evasion/file/location/var_tmp
-exec/install_additional/add_apt_key
+exec/shell/exec
-exec/shell/ignore_output
+fs/directory/create
+fs/file/delete_forcibly
+fs/file/make_executable
+fs/file/times_set
-fs/path/etc
+fs/path/tmp
-fs/path/usr_bin
+fs/path/var
+fs/permission/modify
+impact/remote_access/botnet
-net/download
-net/url/embedded
+persist/cron/etc_d
+persist/cron/tab
+sus/geopolitics
diff --git a/tests/linux/2024.sbcl.market/sbcl.sdiff b/tests/linux/2024.sbcl.market/sbcl.sdiff
index 0d81f2098..592500c94 100644
--- a/tests/linux/2024.sbcl.market/sbcl.sdiff
+++ b/tests/linux/2024.sbcl.market/sbcl.sdiff
@@ -1,27 +1,5 @@
-*** changed: linux/2024.sbcl.market/sbcl.dirty
+*** changed (3 added, 1 removed): linux/2024.sbcl.market/sbcl.dirty
+anti-static/elf/entropy
-c2/addr/url
-c2/tool_transfer/arch
-crypto/rc4
-data/compression/zstd
+data/embedded/zstd
-discover/user/HOME
-discover/user/USER
-evasion/file/location/var_tmp
-exec/dylib/address_check
-exec/dylib/symbol_address
-exec/program
-exec/program/background
-exec/shell/echo
-fs/file/delete
-fs/file/truncate
-fs/link_read
-fs/path/dev
-fs/path/tmp
-fs/path/var
-fs/permission/modify
-fs/proc/self_exe
-fs/symlink_resolve
-fs/tempdir/TEMP
+net/dns/txt
-net/url/embedded
diff --git a/tests/macOS/2023.3CX/libffmpeg.change_decrease.mdiff b/tests/macOS/2023.3CX/libffmpeg.change_decrease.mdiff
index 19dde72ff..c972eb4c9 100644
Binary files a/tests/macOS/2023.3CX/libffmpeg.change_decrease.mdiff and b/tests/macOS/2023.3CX/libffmpeg.change_decrease.mdiff differ
diff --git a/tests/macOS/2023.3CX/libffmpeg.change_increase.mdiff b/tests/macOS/2023.3CX/libffmpeg.change_increase.mdiff
index 1a670ea08..d6cf0d777 100644
Binary files a/tests/macOS/2023.3CX/libffmpeg.change_increase.mdiff and b/tests/macOS/2023.3CX/libffmpeg.change_increase.mdiff differ
diff --git a/tests/macOS/2023.3CX/libffmpeg.change_unrelated.mdiff b/tests/macOS/2023.3CX/libffmpeg.change_unrelated.mdiff
index 856218d9b..168d723f0 100644
--- a/tests/macOS/2023.3CX/libffmpeg.change_unrelated.mdiff
+++ b/tests/macOS/2023.3CX/libffmpeg.change_unrelated.mdiff
@@ -1,4 +1,4 @@
-## Changed: macOS/clean/ls [🟡 MEDIUM → 🔵 LOW]
+## Changed (2 added, 15 removed): macOS/clean/ls [🟡 MEDIUM → 🔵 LOW]
### 2 new behaviors
@@ -27,10 +27,3 @@
| -LOW | [net/url/parse](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/url/parse.yara#url_handle) | Handles URL strings | [URLContext](https://github.com/search?q=URLContext&type=code) |
| -LOW | [process/multithreaded](https://github.com/chainguard-dev/malcontent/blob/main/rules/process/multithreaded.yara#pthread_create) | [creates pthreads](https://man7.org/linux/man-pages/man3/pthread_create.3.html) | [pthread_create](https://github.com/search?q=pthread_create&type=code) |
-### 2 consistent behaviors
-
-| RISK | KEY | DESCRIPTION | EVIDENCE |
-|--|--|--|--|
-| LOW | [c2/addr/url](https://github.com/chainguard-dev/malcontent/blob/main/rules/c2/addr/url.yara#binary_with_url) | binary contains hardcoded URL | [http://crl.apple.com/codesigning.crl0](http://crl.apple.com/codesigning.crl0)
[http://www.apple.com/DTDs/PropertyList](http://www.apple.com/DTDs/PropertyList)
[http://www.apple.com/appleca/root.crl0](http://www.apple.com/appleca/root.crl0)
[https://www.apple.com/appleca/0](https://www.apple.com/appleca/0) |
-| LOW | [exec/shell/TERM](https://github.com/chainguard-dev/malcontent/blob/main/rules/exec/shell/TERM.yara#TERM) | [Look up or override terminal settings](https://www.gnu.org/software/gettext/manual/html_node/The-TERM-variable.html) | [TERM](https://github.com/search?q=TERM&type=code) |
-
diff --git a/tests/macOS/2023.3CX/libffmpeg.dirty.mdiff b/tests/macOS/2023.3CX/libffmpeg.dirty.mdiff
index 1a670ea08..d6cf0d777 100644
Binary files a/tests/macOS/2023.3CX/libffmpeg.dirty.mdiff and b/tests/macOS/2023.3CX/libffmpeg.dirty.mdiff differ
diff --git a/tests/macOS/2023.3CX/libffmpeg.increase.mdiff b/tests/macOS/2023.3CX/libffmpeg.increase.mdiff
index 1a670ea08..d6cf0d777 100644
Binary files a/tests/macOS/2023.3CX/libffmpeg.increase.mdiff and b/tests/macOS/2023.3CX/libffmpeg.increase.mdiff differ
diff --git a/tests/macOS/2023.3CX/libffmpeg.increase_unrelated.mdiff b/tests/macOS/2023.3CX/libffmpeg.increase_unrelated.mdiff
index e244cc49b..845e3d05d 100644
--- a/tests/macOS/2023.3CX/libffmpeg.increase_unrelated.mdiff
+++ b/tests/macOS/2023.3CX/libffmpeg.increase_unrelated.mdiff
@@ -1,4 +1,4 @@
-## Changed: macOS/2023.3CX/libffmpeg.dylib [🔵 LOW → 🟡 MEDIUM]
+## Changed (15 added, 2 removed): macOS/2023.3CX/libffmpeg.dylib [🔵 LOW → 🟡 MEDIUM]
### 15 new behaviors
@@ -27,10 +27,3 @@
| -LOW | [fs/directory/traverse](https://github.com/chainguard-dev/malcontent/blob/main/rules/fs/directory/directory-traverse.yara#fts) | traverse filesystem hierarchy | [_fts_children](https://github.com/search?q=_fts_children&type=code)
[_fts_close](https://github.com/search?q=_fts_close&type=code)
[_fts_open](https://github.com/search?q=_fts_open&type=code)
[_fts_read](https://github.com/search?q=_fts_read&type=code)
[_fts_set](https://github.com/search?q=_fts_set&type=code) |
| -LOW | [fs/link_read](https://github.com/chainguard-dev/malcontent/blob/main/rules/fs/link-read.yara#readlink) | [read value of a symbolic link](https://man7.org/linux/man-pages/man2/readlink.2.html) | [readlink](https://github.com/search?q=readlink&type=code) |
-### 2 consistent behaviors
-
-| RISK | KEY | DESCRIPTION | EVIDENCE |
-|--|--|--|--|
-| LOW | [c2/addr/url](https://github.com/chainguard-dev/malcontent/blob/main/rules/c2/addr/url.yara#binary_with_url) | binary contains hardcoded URL | [http://crl.apple.com/root.crl0](http://crl.apple.com/root.crl0)
[http://crl.apple.com/timestamp.crl0](http://crl.apple.com/timestamp.crl0)
[http://ocsp.apple.com/ocsp03](http://ocsp.apple.com/ocsp03)
[http://www.apple.com/DTDs/PropertyList](http://www.apple.com/DTDs/PropertyList)
[http://www.apple.com/appleca0](http://www.apple.com/appleca0)
[http://www.apple.com/certificateauthority/0](http://www.apple.com/certificateauthority/0)
[https://www.apple.com/appleca/0](https://www.apple.com/appleca/0) |
-| LOW | [exec/shell/TERM](https://github.com/chainguard-dev/malcontent/blob/main/rules/exec/shell/TERM.yara#TERM) | [Look up or override terminal settings](https://www.gnu.org/software/gettext/manual/html_node/The-TERM-variable.html) | [TERM](https://github.com/search?q=TERM&type=code) |
-
diff --git a/tests/macOS/clean/ls.mdiff b/tests/macOS/clean/ls.mdiff
index 51b2bfdef..1ca156c50 100644
--- a/tests/macOS/clean/ls.mdiff
+++ b/tests/macOS/clean/ls.mdiff
@@ -1,4 +1,4 @@
-## Changed: macOS/clean/ls [🟡 MEDIUM → 🔵 LOW]
+## Changed (1 added, 5 removed): macOS/clean/ls [🟡 MEDIUM → 🔵 LOW]
### 1 new behavior
@@ -16,11 +16,3 @@
| -LOW | [discover/system/hostname](https://github.com/chainguard-dev/malcontent/blob/main/rules/discover/system/hostname.yara#gethostname) | [get computer host name](https://man7.org/linux/man-pages/man2/sethostname.2.html) | [gethostname](https://github.com/search?q=gethostname&type=code) |
| -LOW | [net/url/embedded](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/url/embedded.yara#https_url) | contains embedded HTTPS URLs | [https://gnu.org/licenses/gpl.html](https://gnu.org/licenses/gpl.html)
[https://translationproject.org/team/](https://translationproject.org/team/)
[https://wiki.xiph.org/MIME_Types_and_File_Extensions](https://wiki.xiph.org/MIME_Types_and_File_Extensions)
[https://www.gnu.org/software/coreutils/](https://www.gnu.org/software/coreutils/) |
-### 3 consistent behaviors
-
-| RISK | KEY | DESCRIPTION | EVIDENCE |
-|--|--|--|--|
-| LOW | [c2/addr/url](https://github.com/chainguard-dev/malcontent/blob/main/rules/c2/addr/url.yara#binary_with_url) | binary contains hardcoded URL | [http://crl.apple.com/codesigning.crl0](http://crl.apple.com/codesigning.crl0)
[http://www.apple.com/DTDs/PropertyList](http://www.apple.com/DTDs/PropertyList)
[http://www.apple.com/appleca/root.crl0](http://www.apple.com/appleca/root.crl0)
[https://www.apple.com/appleca/0](https://www.apple.com/appleca/0) |
-| LOW | [exec/shell/TERM](https://github.com/chainguard-dev/malcontent/blob/main/rules/exec/shell/TERM.yara#TERM) | [Look up or override terminal settings](https://www.gnu.org/software/gettext/manual/html_node/The-TERM-variable.html) | [TERM](https://github.com/search?q=TERM&type=code) |
-| LOW | [fs/link_read](https://github.com/chainguard-dev/malcontent/blob/main/rules/fs/link-read.yara#readlink) | [read value of a symbolic link](https://man7.org/linux/man-pages/man2/readlink.2.html) | [readlink](https://github.com/search?q=readlink&type=code) |
-
diff --git a/tests/macOS/clean/ls.sdiff.level_2 b/tests/macOS/clean/ls.sdiff.level_2
index db7b91c5d..4cf3f435b 100644
--- a/tests/macOS/clean/ls.sdiff.level_2
+++ b/tests/macOS/clean/ls.sdiff.level_2
@@ -1,2 +1,2 @@
-*** changed: macOS/clean/ls
+*** changed (0 added, 1 removed): macOS/clean/ls
-process/name_set
diff --git a/tests/macOS/clean/ls.sdiff.trigger_2 b/tests/macOS/clean/ls.sdiff.trigger_2
index 5618813e6..1857ac263 100644
--- a/tests/macOS/clean/ls.sdiff.trigger_2
+++ b/tests/macOS/clean/ls.sdiff.trigger_2
@@ -1,10 +1,7 @@
-*** changed: macOS/clean/ls
-c2/addr/url
+*** changed (1 added, 5 removed): macOS/clean/ls
-c2/tool_transfer/arch
-data/compression/lzma
-discover/system/hostname
-exec/shell/TERM
+fs/directory/traverse
-fs/link_read
-net/url/embedded
-process/name_set