Skip to content

fix: guard could be evaded by putting 'snare' in a process argv - #17

Merged
AviOfLagos merged 1 commit into
mainfrom
fix/audit-findings
Aug 26, 2026
Merged

fix: guard could be evaded by putting 'snare' in a process argv#17
AviOfLagos merged 1 commit into
mainfrom
fix/audit-findings

Conversation

@AviOfLagos

Copy link
Copy Markdown
Owner

Found by a shellcheck audit pass (SC2221/SC2222 flagged the redundant pattern, which led to the real problem).

The hole

The guard skipped any process whose command line contained snare anywhere:

case "$cmd" in *snare*|*/.snare/*) continue;; esac

So a payload hid from the guard by naming itself node /tmp/snare-helper.js. snare is public, so this was trivially discoverable by anyone targeting its users.

Confirmed by A/B against a live process

argv containing both snare and a known IOC:

result decoy
pre-fix (main) clean — missed alive
post-fix DETECTED KILLED

Skip is now matched on $SNARE_ROOT/bin/snare, not the bare word.

Also in this pass — shellcheck 10 warnings → 0

  • doctor counted persistence entries with ls | grep, which miscounts filenames containing newlines — in the one place a deliberately awkward filename belongs
  • several local x=$(...) masked exit status
  • three unused variables removed

The guard skipped any process whose command line contained the substring
'snare' anywhere:

    case "$cmd" in *snare*|*/.snare/*) continue;; esac

That is the whole command line, not the executable. So a payload became
invisible to the guard simply by naming itself accordingly:

    node /tmp/snare-helper.js

snare is public and its source is readable, so this was trivially
discoverable by anyone targeting users of the tool.

Confirmed by A/B against a live process whose argv contained both the word
'snare' and a known IOC:

    pre-fix   result: clean          decoy: alive
    post-fix  result: DETECTED       decoy: KILLED

The skip is now matched against the real install path ($SNARE_ROOT/bin/snare)
rather than the bare word.

Also from the same audit pass (shellcheck, 10 warnings -> 0):
  - doctor counted persistence entries with 'ls | grep', which miscounts a
    filename containing a newline. That check exists to inspect persistence
    directories, which is exactly where a deliberately awkward filename
    belongs. Now uses find.
  - several 'local x=$(...)' declarations masked the command's exit status;
    declared and assigned separately.
  - dropped three genuinely unused variables.
@AviOfLagos
AviOfLagos merged commit 1fb1af1 into main Aug 26, 2026
2 checks passed
@AviOfLagos
AviOfLagos deleted the fix/audit-findings branch August 26, 2026 14:59
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.

2 participants