Skip to content

The portable-trampoline shebang idiom reads as identity masquerading (false Tier 5) #3133

Closed

Description

@squid-protocol

Found by the first run of the detection-accuracy harness (PR #3130, closes #3117) against the pinned language-crucible corpus (3,072 files / 51 languages, 0.9964 overall).

Measured

Three crucible files are refused as undeterminable at Tier 5, intensity 0.0, each with an Identity Masking anomaly flag — all reproduced directly:

file proof anomaly flag
tcl/sqlite/speedtest.tcl Identity Conflict (tcl != shell) Identity Masking: Extension (tcl) vs Shebang (shell)
tcl/sqlite/testrunner.tcl Identity Conflict (tcl != shell) same
zig/tigerbeetle/download.ps1 Identity Conflict (powershell != shell) Identity Masking: Extension (powershell) vs Shebang (shell)

All three use the portable-trampoline idiom

The shebang is deliberately a POSIX shell that re-execs the real interpreter. Verbatim from the corpus:

tcl/sqlite/speedtest.tcl — the canonical Tcl portability trick, straight from sqlite's own test harness:

#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" ${1+"$@"}

tcl/sqlite/testrunner.tcl:

#!/bin/sh
# Script to runs tests for SQLite.  Run with option "help" for more info. \
exec tclsh "$0" "$@"

zig/tigerbeetle/download.ps1 — an sh/PowerShell polyglot:

#!/bin/sh
echo `# <#`
./zig/download.sh
exit

This is NOT #3116, and #3127 does not fix it

Stating this explicitly so nobody closes it as a duplicate. In #3116 the shebang matcher was wrong — unanchored substring matching made tclsh match sh. Here the matcher is right: the shebang genuinely is #!/bin/sh, so basename-exact matching resolves it to shell just as correctly as before, and the conflict still fires.

The defect is not in shebang resolution at all. It is the Identity Conflict Trap treating a legitimate bootstrap as a masquerade.

Severity

Same shape as #3116's: the file is excluded from analysis entirely (intensity 0.0, no rules run) and reported as a security anomaly. So a customer sees the scanner accusing a stock sqlite test script of identity masquerading — a false malware-shaped finding on canonical upstream code.

Fix directions to weigh (un-adjudicated)

  1. When the extension's language and the shebang disagree, scan the first few lines for an exec <interpreter> naming the extension's language; treat that as a trampoline and trust the extension.
  2. Require the conflicting shebang to be a non-shell interpreter before raising a conflict at all — a generic sh shebang is the standard bootstrap vehicle and carries little identity weight.
  3. Keep the extension's verdict but attach an informational note rather than refusing.

The constraint that matters: whatever is chosen must not weaken detection of a genuinely mislabelled executable, which is what the trap exists for. Option 2 is the broadest and therefore needs the most care — it would also stop flagging a real .tcl file that is actually a shell script.

Related

#3116 / #3127 (the shebang-matching bug and its fix — distinct from this), #3117 (the harness that found this).

Activity

  1. added
    bugUnintended behavior or logic failure in the engine
    core-engineModifications to the central physics and parsing engine
    on Sep 17, 2026
  2. squid-protocol commented on Sep 17, 2026

    @squid-protocol
    OwnerAuthor

    Fixed in #3127 (merged 2026-09-17T10:27:25Z, commit bede481f+). The PR referenced this issue but without a closing keyword, so it stayed open — closing manually.

    Regression coverage in tests/core_engine/test_detection_resolution_order.py. Measured effect on the #3117 harness: overall accuracy 0.9964 -> 0.9974, refusals 3 -> 1, Tier 5 conflicts 3 -> 1.

  3. squid-protocol commented on Sep 17, 2026

    @squid-protocol
    OwnerAuthor

    Reopening — my earlier close was premature and wrong.

    #3127 merged as a squash containing only its first half (through the csh/pfsh/luatrace triggers). The trampoline and prefix-anchor fixes were in a later commit that did NOT land: grep -c _trampoline_interpreter on main returns 0. My close comment attributed the fix to a merge that does not contain it.

    The fix is real and tested, but currently only on the fix/detection-3116 branch. Re-landing it on current main now; will close against the merge commit that actually carries it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugUnintended behavior or logic failure in the enginecore-engineModifications to the central physics and parsing engine

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions