Repository navigation
Scan extension-less entry points using their shebang - #885
Open
VictorMartins3 wants to merge 1 commit into
Open
VictorMartins3 wants to merge 1 commit into
VictorMartins3 wants to merge 1 commit into
Conversation
Every source code rule selects files through path_include globs, and all of
them select by extension. A package's `bin` target normally has none,
because the shell runs it through the shebang, so that file is never handed
to any rule even though it is what a consumer executes directly.
Same payload in two places, scanned with the full npm rule set:
index.js 8 issues, including threat-filesystem-read and
threat-runtime-environment-read
bin/tool 0 issues
When a file has no extension and does not match path_include, its shebang
now stands in for one: `#!/usr/bin/env node` makes it eligible for the
globs that select .js, python3 for .py, bash for .sh. A file with no
shebang is still skipped, so a LICENSE or a data blob does not start
reaching every rule.
Each rule walks the tree separately, so the probe result is cached per
scan and each extension-less file is read once rather than once per rule.
VictorMartins3
force-pushed
the
VictorMartins3/bin-entrypoints
branch
from
September 17, 2026 04:02
cb85026 to
eb38cb9
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's up
Every source code rule filters files through
path_include, and all 23distinct globs across the 54 rules select by extension:
An npm package's
bintarget normally has no extension, because the shellruns it through the shebang.
"bin": {"tool": "./bin/tool"}is the usualshape. Nothing in that list matches
bin/tool, so the file never reachesa rule, and it's the one a consumer executes directly.
Same payload, two locations, full npm rule set:
Worth saying: this isn't only a capability-tagging gap. Two
threat-*rules fire on the first and neither fires on the second, so the whole
source code analyzer is blind to the file.
Sampling published npm packages that declare a
bin, roughly one in ninepoints it at a path with no source extension.
What I changed
When a file has no extension and doesn't match
path_include, its shebangstands in for one.
#!/usr/bin/env nodemakes it eligible for the globsthat select
.js,python3for.py,bashfor.sh, and so on, so ashell script doesn't suddenly get handed to the Python rules.
A file with no shebang is still skipped — the fallback is the interpreter
line, not the absence of an extension, so a LICENSE or a data blob doesn't
start reaching every rule.
Each rule walks the tree on its own, so the probe is cached per scan and
each extension-less file is read once instead of 54 times. It's a 128-byte
read.
An alternative I considered
Resolving
package.json'sbinentries and always scanning those. Moreprecise for npm, but ecosystem-specific and it wouldn't cover a shebang
script that isn't declared in
bin. The shebang approach felt like thebetter fit for a multi-ecosystem scanner, but I'm happy to redo it the
other way if you'd rather keep the analyzer ecosystem-agnostic.
Tests
Three in
tests/core/test_sourcecode_analyzer.py: the entry point isscanned, an extension-less file without a shebang still isn't, and a
shebang maps to its own language only. First two fail on
v3.tests/analyzer/metadatahas 3 failures and 11 errors on a cleanv3checkout here, unrelated to this.